From cd072c875c334b1140e4f797a37a9e991d53e2b5 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Wed, 26 Feb 2025 16:29:27 +0700
Subject: <iman> CR repear order

---
 src/lib/transaction/components/Transactions.jsx | 294 +++++++++++++++++++++---
 1 file changed, 265 insertions(+), 29 deletions(-)

(limited to 'src/lib/transaction/components/Transactions.jsx')

diff --git a/src/lib/transaction/components/Transactions.jsx b/src/lib/transaction/components/Transactions.jsx
index 92bdd276..a8685105 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -4,9 +4,10 @@ import { toast } from 'react-hot-toast';
 import {
   EllipsisVerticalIcon,
   MagnifyingGlassIcon,
+  ChevronDownIcon,
+  ChevronUpIcon,
 } from '@heroicons/react/24/outline';
 import useAuth from '@/core/hooks/useAuth';
-
 import {
   downloadPurchaseOrder,
   downloadQuotation,
@@ -28,32 +29,31 @@ import Menu from '@/lib/auth/components/Menu';
 import * as XLSX from 'xlsx';
 import getSite from '../api/listSiteApi';
 import transactionsApi from '../api/transactionsApi';
-
+import { motion } from 'framer-motion';
+import Image from '@/core/components/elements/Image/Image';
 const Transactions = ({ context = '' }) => {
   const auth = useAuth();
   const router = useRouter();
-  const { q = '', page = 1, site = null } = router.query;
-
-  const limit = 15;
+  const { q = '', page = 1, site = null, limit = 15 } = router.query;
 
   const [inputQuery, setInputQuery] = useState(q);
   const [toOthers, setToOthers] = useState(null);
   const [toCancel, setToCancel] = useState(null);
   const [listSites, setListSites] = useState([]);
-
+  const [isOpen, setIsOpen] = useState(false);
   const [siteFilter, setSiteFilter] = useState(site);
-
+  const [pageNew, setPageNew] = useState(page);
+  const [limitNew, setLimitNew] = useState(limit);
   const query = {
     name: q,
-    offset: (page - 1) * limit,
+    offset: (pageNew - 1) * limitNew,
     context,
-    limit,
+    limit: limitNew,
     site:
       siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
   };
-
   const { transactions } = useTransactions({ query });
-
+  console.log('transactions', transactions);
   const fetchSite = async () => {
     const site = await getSite();
     setListSites(site.sites);
@@ -70,7 +70,7 @@ const Transactions = ({ context = '' }) => {
     setToCancel(null);
   };
 
-  const pageCount = Math.ceil(transactions?.data?.saleOrderTotal / limit);
+  const pageCount = Math.ceil(transactions?.data?.saleOrderTotal / limitNew);
   let pageQuery = _.omit(query, ['limit', 'offset', 'context']);
   pageQuery = _.pickBy(
     pageQuery,
@@ -137,6 +137,58 @@ const Transactions = ({ context = '' }) => {
     XLSX.writeFile(workbook, 'transactions.xlsx');
   };
 
+  const handleExportCSV = async () => {
+    const dataToExport = await getAllData();
+
+    exportToCSV(dataToExport?.saleOrders, siteFilter);
+  };
+
+  const exportToCSV = (data, siteFilter) => {
+    const fieldsToExport = [
+      'No. Transaksi',
+      'No. PO',
+      'Tanggal',
+      'Created By',
+      'Salesperson',
+      '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),
+        saleOrder.status,
+      ];
+
+      if (siteFilter) {
+        row.push(siteFilter);
+      }
+
+      return row.join(',');
+    });
+
+    const csvContent =
+      'data:text/csv;charset=utf-8,' +
+      [fieldsToExport.join(','), ...rowsToExport].join('\n');
+
+    const encodedUri = encodeURI(csvContent);
+    const link = document.createElement('a');
+    link.setAttribute('href', encodedUri);
+    link.setAttribute('download', 'transactions.csv');
+    document.body.appendChild(link);
+    link.click();
+    document.body.removeChild(link);
+  };
+
   const getAllData = async () => {
     const query = {
       name: q,
@@ -144,7 +196,7 @@ const Transactions = ({ context = '' }) => {
       site:
         siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
     };
-    const queryString = toQuery(query)
+    const queryString = toQuery(query);
     const data = await transactionsApi({ query: queryString });
     return data;
   };
@@ -155,6 +207,25 @@ const Transactions = ({ context = '' }) => {
     exportToExcel(dataToExport?.saleOrders, siteFilter);
   };
 
+  const handleDownload = (format) => {
+    handleExport(format);
+    setIsOpen(false);
+  };
+
+  const handleExport = (format) => {
+    if (format === 'csv') {
+      handleExportCSV();
+    } else if (format === 'xlsx') {
+      handleExportExcel();
+    }
+  };
+
+  const startItem = 1 + (pageNew - 1) * limitNew;
+  const endItem = Math.min(
+    limitNew * pageNew,
+    transactions?.data?.saleOrderTotal
+  );
+
   useEffect(() => {
     fetchSite();
   }, []);
@@ -328,14 +399,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-6 items-center justify-between '>
               <h1 className='text-title-sm font-semibold'>
                 Daftar Transaksi{' '}
                 {transactions?.data?.saleOrders
-                  ? `(${transactions?.data?.saleOrders.length})`
+                  ? `(${transactions?.data?.saleOrderTotal})`
                   : ''}
               </h1>
-              <div className='grid grid-cols-2 gap-2'>
+              <div className='relative inline-block text-left'>
+                <button
+                  onClick={() => setIsOpen(!isOpen)}
+                  type='button'
+                  className='btn-light bg-slate-50 mt-3 w-full gap-2 items-center flex flex-row !text-gray_r-11 px-4 py-3 mb-2'
+                >
+                  <p>Export</p>
+                  <motion.div
+                    animate={{ rotate: isOpen ? 180 : 0 }}
+                    transition={{ duration: 0.2, ease: 'easeInOut' }}
+                  >
+                    <ChevronDownIcon className='w-5' />
+                  </motion.div>
+                </button>
+
+                {isOpen && (
+                  <motion.div
+                    initial={{ opacity: 0, y: -10 }}
+                    animate={{ opacity: 1, y: 0 }}
+                    exit={{ opacity: 0, y: -10 }}
+                    transition={{ duration: 0.2, ease: 'easeInOut' }}
+                    className='absolute mt-2 w-fit py-1 bg-white border border-gray-300 rounded-md shadow-lg'
+                  >
+                    <button
+                      onClick={() => handleDownload('csv')}
+                      className='block w-full px-4 py-2 text-left hover:bg-gray-200 text-nowrap'
+                    >
+                      Download CSV
+                    </button>
+                    <button
+                      onClick={() => handleDownload('xlsx')}
+                      className='block w-full px-4 py-2 text-left hover:bg-gray-200 text-nowrap'
+                    >
+                      Download XLSX
+                    </button>
+                  </motion.div>
+                )}
+              </div>
+            </div>
+            <div className='flex flex-row items-center justify-between mb-2'>
+              <div className='flex flex-col gap-2 pb-2'>
                 {listSites?.length > 0 ? (
                   <select
                     value={siteFilter}
@@ -349,7 +460,9 @@ const Transactions = ({ context = '' }) => {
                       </option>
                     ))}
                   </select>
-                ) : (<div></div>)}
+                ) : (
+                  <div></div>
+                )}
 
                 <form className='flex gap-x-1' onSubmit={handleSubmit}>
                   <input
@@ -367,14 +480,138 @@ const Transactions = ({ context = '' }) => {
                   </button>
                 </form>
               </div>
+              <div className='flex flex-row gap-4 items-center justify-center'>
+                <p>
+                  Menampilkan {startItem}-
+                  {endItem ? endItem : transactions?.data?.saleOrderTotal} dari{' '}
+                  {transactions?.data?.saleOrderTotal}
+                </p>
+                <select
+                  id='limitSelect'
+                  value={limitNew}
+                  onChange={(e) => {
+                    setLimitNew(Number(e.target.value));
+                    setPageNew(1);
+                  }}
+                  className='border p-2'
+                >
+                  <option value={10}>10</option>
+                  <option value={15}>15</option>
+                  <option value={20}>20</option>
+                </select>
+              </div>
+            </div>
+            <div className='flex'>
+              {!transactions.isLoading &&
+                (!transactions?.data?.saleOrders ||
+                  transactions?.data?.saleOrders?.length == 0) && (
+                  <div className='justify-center p-4'>
+                    <p className='text-gray-500 text-center '>
+                      Tidak Ada Transaksi
+                    </p>
+                  </div>
+                )}
+
+              {transactions && transactions.data?.saleOrders?.length > 0 && (
+                <div className='flex flex-col gap-4 w-full'>
+                  {transactions.data.saleOrders.map((saleOrder, index) => (
+                    <div
+                      key={index}
+                      className='border p-2 hover:border-red-500 w-full rounded-sm'
+                    >
+                      {/* <Link
+                        href={`/my/quotations/${saleOrder?.id}`}
+                        className='hover:border-red-500 block w-full'
+                      > */}
+                      <div className='flex flex-row justify-between items-center py-2'>
+                        <div className='flex justify-center gap-3'>
+                          <TransactionStatusBadge status={saleOrder.status} />
+                          <p className='text-red-500'>{saleOrder.name}</p>
+                          <p>
+                            Salesperson:{' '}
+                            {
+                              <span className='font-semibold'>
+                                {saleOrder.sales}
+                              </span>
+                            }
+                          </p>
+                        </div>
+                        <div>
+                          Tanggal Pesanan:{' '}
+                          <span className='font-semibold'>
+                            {saleOrder.dateOrder.split(' ')[0] || '-'}
+                          </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-4/5 flex-col gap-2'>
+                          <div className='flex gap-2'>
+                            <div>
+                              <Image
+                                src={saleOrder.products[0]?.parent?.image}
+                                alt={saleOrder.products[0]?.name}
+                                className='object-contain object-center border border-gray_r-6 h-32 w-full rounded-md'
+                              />
+                            </div>
+                            <div className='flex flex-col gap-3 justify-start'>
+                              <p className='flex flex-row gap-2'>
+                                <span className='text-sm'>Nomor PO:</span>
+                                <span className='text-sm text-red-500 font-semibold'>
+                                  {saleOrder.purchaseOrderName || '-'}
+                                </span>
+                              </p>
+                              <p className='line-clamp-2 leading-6 tracking-wide opacity-90 !text-gray_r-12 font-semibold text-nowrap'>
+                                {saleOrder.products[0]?.parent?.name}
+                              </p>
+                              <p className='opacity-85 !text-gray_r-12'>
+                                {saleOrder.products[0]?.quantity} x{' '}
+                                {currencyFormat(
+                                  saleOrder.products[0]?.price?.priceDiscount
+                                )}
+                              </p>
+                              <div className='flex flex-row justify-start items-center'>
+                                {saleOrder.products?.length > 1 && (
+                                  <div className='flex flex-row gap-1 justify-start items-center'>
+                                    {saleOrder.products
+                                      .slice(1)
+                                      .map((product, index) => (
+                                        <Image
+                                          key={index} // Tambahkan key untuk setiap elemen dalam map()
+                                          src={product?.parent?.image}
+                                          alt={product?.name}
+                                          className='object-contain object-center border border-gray_r-6 h-8 w-8 rounded-md'
+                                        />
+                                      ))}
+                                    <Link
+                                      href={`/my/quotations/${saleOrder?.id}`}
+                                      className='text-sm text-red-500 text-nowrap'
+                                    >
+                                      Lihat semua produk
+                                    </Link>
+                                  </div>
+                                )}
+                              </div>
+                            </div>
+                          </div>
+                          <div className='flex flex-row w-full text-nowrap gap-2'>
+                            <span className='text-sm'>
+                              pesanan dibuat oleh:
+                            </span>
+                            <p className='text-sm font-semibold'>
+                              {saleOrder.address.customer?.name || '-'}
+                            </p>
+                          </div>
+                        </div>
+                        <div className='w-[1px] h-24 bg-gray-300'></div>
+                        <div className='w-1/5'>Total harga</div>
+                      </div>
+                      {/* </Link> */}
+                    </div>
+                  ))}
+                </div>
+              )}
             </div>
-            <button
-              onClick={handleExportExcel}
-              type='button'
-              className='btn-solid-red px-3 py-2 mr-auto mb-2'
-            >
-              <span>Download</span>
-            </button>
             <table className='table-data'>
               <thead>
                 <tr>
@@ -382,9 +619,7 @@ const Transactions = ({ context = '' }) => {
                   <th>No. PO</th>
                   <th>Tanggal</th>
                   <th>Created By</th>
-                  {auth?.feature?.soApproval && (
-                    <th>Site</th>
-                  )}
+                  {auth?.feature?.soApproval && <th>Site</th>}
                   <th className='!text-left'>Salesperson</th>
                   <th className='!text-left'>Total</th>
                   <th>Status</th>
@@ -439,8 +674,9 @@ const Transactions = ({ context = '' }) => {
 
             <Pagination
               pageCount={pageCount}
-              currentPage={parseInt(page)}
-              url={router.pathname + (pageQuery ? `?${pageQuery}` : '')}
+              currentPage={parseInt(pageNew)}
+              // url={router.pathname + (pageQuery ? `?${pageQuery}` : '')}
+              url={`/my/transactions?${toQuery(_.omit(query, ['page']))}`}
               className='mt-2 mb-2'
             />
           </div>
-- 
cgit v1.2.3

