summaryrefslogtreecommitdiff
path: root/src/lib/transaction
diff options
context:
space:
mode:
authorHATEC\SPVDEV001 <tri.susilo@altama.co.id>2024-05-21 14:10:36 +0700
committerHATEC\SPVDEV001 <tri.susilo@altama.co.id>2024-05-21 14:10:36 +0700
commit6650a080208b09a50f286cd197c166ebdeca6d8a (patch)
tree250553935dc4666fb85873300c7a99b31b0a8fb0 /src/lib/transaction
parent145f9edfd32b385771483b9b95a9fa0fa24c2dec (diff)
filter site dan export
Diffstat (limited to 'src/lib/transaction')
-rw-r--r--src/lib/transaction/components/Transactions.jsx299
1 files changed, 219 insertions, 80 deletions
diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx
index be63effd..9485449d 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -1,63 +1,139 @@
-import { useRouter } from 'next/router'
-import { useState } from 'react'
-import { toast } from 'react-hot-toast'
-import { EllipsisVerticalIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline'
+import { useRouter } from 'next/router';
+import { useEffect, useState } from 'react';
+import { toast } from 'react-hot-toast';
+import {
+ EllipsisVerticalIcon,
+ MagnifyingGlassIcon,
+} from '@heroicons/react/24/outline';
+import useAuth from '@/core/hooks/useAuth';
-import { downloadPurchaseOrder, downloadQuotation } from '../utils/transactions'
-import useTransactions from '../hooks/useTransactions'
-import currencyFormat from '@/core/utils/currencyFormat'
-import cancelTransactionApi from '../api/cancelTransactionApi'
-import TransactionStatusBadge from './TransactionStatusBadge'
-import Spinner from '@/core/components/elements/Spinner/Spinner'
-import Link from '@/core/components/elements/Link/Link'
-import BottomPopup from '@/core/components/elements/Popup/BottomPopup'
-import Pagination from '@/core/components/elements/Pagination/Pagination'
-import { toQuery } from 'lodash-contrib'
-import _ from 'lodash'
-import Alert from '@/core/components/elements/Alert/Alert'
-import MobileView from '@/core/components/views/MobileView'
-import DesktopView from '@/core/components/views/DesktopView'
-import Menu from '@/lib/auth/components/Menu'
+import {
+ downloadPurchaseOrder,
+ downloadQuotation,
+} from '../utils/transactions';
+import useTransactions from '../hooks/useTransactions';
+import currencyFormat from '@/core/utils/currencyFormat';
+import cancelTransactionApi from '../api/cancelTransactionApi';
+import TransactionStatusBadge from './TransactionStatusBadge';
+import Spinner from '@/core/components/elements/Spinner/Spinner';
+import Link from '@/core/components/elements/Link/Link';
+import BottomPopup from '@/core/components/elements/Popup/BottomPopup';
+import Pagination from '@/core/components/elements/Pagination/Pagination';
+import { toQuery } from 'lodash-contrib';
+import _ from 'lodash';
+import Alert from '@/core/components/elements/Alert/Alert';
+import MobileView from '@/core/components/views/MobileView';
+import DesktopView from '@/core/components/views/DesktopView';
+import Menu from '@/lib/auth/components/Menu';
+import * as XLSX from 'xlsx';
const Transactions = ({ context = '' }) => {
- const router = useRouter()
- const { q = '', page = 1 } = router.query
+ const auth = useAuth();
+ const router = useRouter();
+ const { q = '', page = 1, site = null } = router.query;
- const limit = 15
+ const limit = 15;
+
+ const [inputQuery, setInputQuery] = useState(q);
+ const [toOthers, setToOthers] = useState(null);
+ const [toCancel, setToCancel] = useState(null);
+
+ const [siteFilter, setSiteFilter] = useState(site);
const query = {
name: q,
offset: (page - 1) * limit,
context,
- limit
- }
- const { transactions } = useTransactions({ query })
+ limit,
+ site:
+ siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
+ };
- const [inputQuery, setInputQuery] = useState(q)
- const [toOthers, setToOthers] = useState(null)
- const [toCancel, setToCancel] = useState(null)
+ const { transactions } = useTransactions({ query });
const submitCancelTransaction = async () => {
const isCancelled = await cancelTransactionApi({
- transaction: toCancel
- })
+ transaction: toCancel,
+ });
if (isCancelled) {
- toast.success('Berhasil batalkan transaksi')
- transactions.refetch()
+ toast.success('Berhasil batalkan transaksi');
+ transactions.refetch();
}
- setToCancel(null)
- }
+ setToCancel(null);
+ };
- const pageCount = Math.ceil(transactions?.data?.saleOrderTotal / limit)
- let pageQuery = _.omit(query, ['limit', 'offset', 'context'])
- pageQuery = _.pickBy(pageQuery, _.identity)
- pageQuery = toQuery(pageQuery)
+ const pageCount = Math.ceil(transactions?.data?.saleOrderTotal / limit);
+ let pageQuery = _.omit(query, ['limit', 'offset', 'context']);
+ pageQuery = _.pickBy(
+ pageQuery,
+ (value, key) => value !== '' && !(key === 'page' && value === '1')
+ );
+ pageQuery = toQuery(pageQuery);
const handleSubmit = (e) => {
- e.preventDefault()
- router.push(`${router.pathname}?q=${inputQuery}`)
- }
+ e.preventDefault();
+ const queryParams = {};
+ if (inputQuery) queryParams.q = inputQuery;
+ if (siteFilter) queryParams.site = siteFilter;
+ router.push({
+ pathname: router.pathname,
+ query: queryParams,
+ });
+ };
+
+ const handleSiteFilterChange = (e) => {
+ setSiteFilter(e.target.value);
+ const queryParams = {};
+ if (inputQuery) queryParams.q = inputQuery;
+ if (e.target.value) queryParams.site = e.target.value;
+ router.push({
+ pathname: router.pathname,
+ query: queryParams,
+ });
+ };
+
+ const exportToExcel = (data, siteFilter) => {
+ const fieldsToExport = [
+ 'No. Transaksi',
+ 'No. PO',
+ 'Tanggal',
+ 'Created By',
+ 'Salesperson',
+ 'Total',
+ 'Status',
+ ];
+ const rowsToExport = [];
+
+ data.forEach((saleOrder) => {
+ const row = {
+ 'No. Transaksi': saleOrder.name,
+ 'No. PO': saleOrder.purchaseOrderName || '-',
+ 'Tanggal': saleOrder.dateOrder || '-',
+ 'Created By': saleOrder.address.customer?.name || '-',
+ 'Salesperson': saleOrder.sales,
+ 'Total': currencyFormat(saleOrder.amountTotal),
+ 'Status': saleOrder.status,
+ };
+ if(siteFilter){
+ row['Site'] = siteFilter;
+ }
+ rowsToExport.push(row);
+ });
+ const worksheet = XLSX.utils.json_to_sheet(rowsToExport, {
+ header: fieldsToExport,
+ });
+
+ const workbook = XLSX.utils.book_new();
+ XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
+ XLSX.writeFile(workbook, 'transactions.xlsx');
+ };
+
+ const handleExportExcel = () => {
+ const dataToExport = transactions.data.saleOrders;
+
+ exportToExcel(dataToExport, siteFilter);
+ };
return (
<>
<MobileView>
@@ -81,17 +157,23 @@ const Transactions = ({ context = '' }) => {
</div>
)}
- {!transactions.isLoading && transactions.data?.saleOrders?.length === 0 && (
- <Alert type='info' className='text-center'>
- Tidak ada transaksi
- </Alert>
- )}
+ {!transactions.isLoading &&
+ transactions.data?.saleOrders?.length === 0 && (
+ <Alert type='info' className='text-center'>
+ Tidak ada transaksi
+ </Alert>
+ )}
{transactions.data?.saleOrders?.map((saleOrder, index) => (
- <div className='p-4 shadow border border-gray_r-3 rounded-md' key={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}/${saleOrder.id}`}>
- <span className='text-caption-2 text-gray_r-11'>No. Transaksi</span>
+ <span className='text-caption-2 text-gray_r-11'>
+ No. Transaksi
+ </span>
<h2 className='text-danger-500 mt-1'>{saleOrder.name}</h2>
</Link>
<div className='flex gap-x-1 justify-end'>
@@ -105,13 +187,17 @@ const Transactions = ({ context = '' }) => {
<Link href={`${router.pathname}/${saleOrder.id}`}>
<div className='grid grid-cols-2 mt-3'>
<div>
- <span className='text-caption-2 text-gray_r-11'>No. Purchase Order</span>
+ <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>
+ <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>
@@ -120,10 +206,14 @@ const Transactions = ({ context = '' }) => {
<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>
+ <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>
+ <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>
@@ -140,14 +230,18 @@ const Transactions = ({ context = '' }) => {
className='mt-2 mb-2'
/>
- <BottomPopup title='Lainnya' active={toOthers} close={() => setToOthers(null)}>
+ <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'
disabled={!toOthers?.purchaseOrderFile}
onClick={() => {
- downloadPurchaseOrder(toOthers)
- setToOthers(null)
+ downloadPurchaseOrder(toOthers);
+ setToOthers(null);
}}
>
Download PO
@@ -156,8 +250,8 @@ const Transactions = ({ context = '' }) => {
className='text-left disabled:opacity-60'
disabled={toOthers?.status != 'draft'}
onClick={() => {
- downloadQuotation(toOthers)
- setToOthers(null)
+ downloadQuotation(toOthers);
+ setToOthers(null);
}}
>
Download Quotation
@@ -166,8 +260,8 @@ const Transactions = ({ context = '' }) => {
className='text-left disabled:opacity-60'
disabled={toOthers?.status != 'waiting'}
onClick={() => {
- setToCancel(toOthers)
- setToOthers(null)
+ setToCancel(toOthers);
+ setToOthers(null);
}}
>
Batalkan Transaksi
@@ -175,7 +269,11 @@ const Transactions = ({ context = '' }) => {
</div>
</BottomPopup>
- <BottomPopup active={toCancel} close={() => setToCancel(null)} title='Batalkan Transaksi'>
+ <BottomPopup
+ active={toCancel}
+ close={() => setToCancel(null)}
+ title='Batalkan Transaksi'
+ >
<div className='leading-7 text-gray_r-12/80'>
Apakah anda yakin membatalkan transaksi{' '}
<span className='underline'>{toCancel?.name}</span>?
@@ -188,7 +286,11 @@ const Transactions = ({ context = '' }) => {
>
Ya, Batalkan
</button>
- <button className='btn-light flex-1' type='button' onClick={() => setToCancel(null)}>
+ <button
+ className='btn-light flex-1'
+ type='button'
+ onClick={() => setToCancel(null)}
+ >
Batal
</button>
</div>
@@ -202,24 +304,54 @@ const Transactions = ({ context = '' }) => {
<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'>
+ <div className='flex mb-2 items-center justify-between'>
<h1 className='text-title-sm font-semibold'>
Daftar Transaksi{' '}
- {transactions?.data?.saleOrders ? `(${transactions?.data?.saleOrders.length})` : ''}
+ {transactions?.data?.saleOrders
+ ? `(${transactions?.data?.saleOrders.length})`
+ : ''}
</h1>
- <form className='flex gap-x-2' onSubmit={handleSubmit}>
- <input
- type='text'
+ <div className='grid grid-cols-2 gap-2'>
+ <select
+ value={siteFilter}
+ onChange={handleSiteFilterChange}
className='form-input'
- placeholder='Cari Transaksi...'
- value={inputQuery}
- onChange={(e) => setInputQuery(e.target.value)}
- />
- <button className='btn-light bg-transparent px-3' type='submit'>
- <MagnifyingGlassIcon className='w-6' />
- </button>
- </form>
+ >
+ <option value=''>Semua</option>
+ <option value='Depok'>Depok</option>
+ <option value='Padang'>Padang</option>
+ <option value='berau'>Berau</option>
+ </select>
+ <form className='flex gap-x-1' onSubmit={handleSubmit}>
+ <input
+ type='text'
+ className='form-input'
+ placeholder='Cari Transaksi...'
+ 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>
</div>
+ <button
+ onClick={handleExportExcel}
+ className='hover:text-blue-400 rounded inline-flex items-center mb-2'
+ >
+ <svg
+ class='fill-current w-4 h-4 mr-2'
+ xmlns='http://www.w3.org/2000/svg'
+ viewBox='0 0 20 20'
+ >
+ <path d='M13 8V2H7v6H2l8 8 8-8h-5zM0 18h20v2H0v-2z' />
+ </svg>
+ <span>Export</span>
+ </button>
<table className='table-data'>
<thead>
<tr>
@@ -252,13 +384,20 @@ const Transactions = ({ context = '' }) => {
{transactions.data?.saleOrders?.map((saleOrder) => (
<tr key={saleOrder.id}>
<td>
- <Link className='whitespace-nowrap' href={`${router.pathname}/${saleOrder.id}`}>{saleOrder.name}</Link>
+ <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>
<td className='!text-left'>{saleOrder.sales}</td>
- <td className='!text-left'>{currencyFormat(saleOrder.amountTotal)}</td>
+ <td className='!text-left'>
+ {currencyFormat(saleOrder.amountTotal)}
+ </td>
<td>
<div className='flex justify-center'>
<TransactionStatusBadge status={saleOrder.status} />
@@ -272,14 +411,14 @@ const Transactions = ({ context = '' }) => {
<Pagination
pageCount={pageCount}
currentPage={parseInt(page)}
- url={router.pathname + pageQuery}
+ url={router.pathname + (pageQuery ? `?${pageQuery}` : '')}
className='mt-2 mb-2'
/>
</div>
</div>
</DesktopView>
</>
- )
-}
+ );
+};
-export default Transactions
+export default Transactions;