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


From faf6403595602d78b502acfacc721923addbf4a8 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Mon, 3 Mar 2025 16:38:10 +0700
Subject: <iman> update code

---
 src/lib/transaction/components/Transactions.jsx | 487 ++++++++++++++++--------
 1 file changed, 337 insertions(+), 150 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 a8685105..64ae9393 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -31,11 +31,30 @@ import getSite from '../api/listSiteApi';
 import transactionsApi from '../api/transactionsApi';
 import { motion } from 'framer-motion';
 import Image from '@/core/components/elements/Image/Image';
+import { upsertUserCart } from '~/services/cart';
+import { useProductCartContext } from '@/contexts/ProductCartContext';
+import { Swiper, SwiperSlide } from 'swiper/react';
+import 'swiper/css';
 const Transactions = ({ context = '' }) => {
   const auth = useAuth();
   const router = useRouter();
-  const { q = '', page = 1, site = null, limit = 15 } = router.query;
-
+  const {
+    q = '',
+    page = 1,
+    site = null,
+    limit = 15,
+    status = 'all',
+  } = router.query;
+  const {
+    productCart,
+    setRefreshCart,
+    setProductCart,
+    refreshCart,
+    isLoading,
+    setIsloading,
+  } = useProductCartContext();
+  console.log('context', context);
+  console.log('router.query', router.query);
   const [inputQuery, setInputQuery] = useState(q);
   const [toOthers, setToOthers] = useState(null);
   const [toCancel, setToCancel] = useState(null);
@@ -44,16 +63,32 @@ 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 [contextNew, setcontextNew] = useState(router.query.context || context);
   const query = {
     name: q,
     offset: (pageNew - 1) * limitNew,
-    context,
+    context: contextNew,
     limit: limitNew,
+    status: statusNew,
     site:
       siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
   };
+
+  const statuses = [
+    { id: 'all', label: 'Semua' },
+    { id: 'quotation', label: 'Pending Quotation' },
+    { id: 'diterima', label: 'Pesanan Diterima' },
+    { id: 'diproses', label: 'Pesanan Diproses' },
+    { id: 'dikirim', label: 'Pesanan Dikirim' },
+    { id: 'selesai', label: 'Pesanan Selesai' },
+    { id: 'cancel', label: 'Pesanan Dibatalkan' },
+  ];
+
+  console.log('query', query);
   const { transactions } = useTransactions({ query });
-  console.log('transactions', transactions);
+  // console.log('transactions', transactions);
   const fetchSite = async () => {
     const site = await getSite();
     setListSites(site.sites);
@@ -229,6 +264,67 @@ const Transactions = ({ context = '' }) => {
   useEffect(() => {
     fetchSite();
   }, []);
+
+  const handleBuyBack = async (products) => {
+    // if (status === 'success') return;
+
+    try {
+      // setStatus('loading');
+
+      const results = await Promise.all(
+        products.map((product) =>
+          upsertUserCart({
+            userId: auth.id,
+            type: 'product',
+            id: product.id,
+            qty: product.quantity,
+            selected: true,
+            source: 'buy', // Tetap gunakan 'buy' agar bisa masuk ke halaman pembelian
+            qtyAppend: false,
+          })
+        )
+      );
+
+      // console.log(`Produk berhasil dimasukkan ke dalam cart`, results);
+
+      // ✅ Panggil setRefreshCart(true) setiap kali satu produk berhasil ditambahkan
+
+      setRefreshCart(true);
+
+      // setStatus('idle');
+      toast.success('Semua produk berhasil ditambahkan ke keranjang belanja');
+      // Tampilkan notifikasi
+      // toast({
+      //   title: 'Tambah ke keranjang',
+      //   description: 'Semua produk berhasil ditambahkan ke keranjang belanja',
+      //   status: 'success',
+      //   duration: 3000,
+      //   isClosable: true,
+      //   position: 'top',
+      // });
+
+      // Redirect ke halaman checkout
+      router.push('/shop/checkout?source=buy');
+    } catch (error) {
+      console.error('Gagal menambahkan produk ke keranjang:', error);
+      // setStatus('error');
+    }
+  };
+
+  const handleStatusChange = (status) => {
+    setStatusNew(status);
+
+    if (['quotation', 'cancel', 'diterima', ''].includes(status)) {
+      setcontextNew('quotation');
+    } else {
+      setcontextNew('');
+    }
+
+    if (status === 'all') {
+      router.push('/my/transactions');
+    }
+  };
+
   return (
     <>
       <MobileView>
@@ -445,66 +541,126 @@ const Transactions = ({ context = '' }) => {
                 )}
               </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}
-                    onChange={handleSiteFilterChange}
-                    className='form-input'
+            <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'>
+                    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
+                    do eiusmod tempor incididunt ut labore et dolore magna
+                    aliqua.
+                  </span>
+                </div>
+              </div>
+            </div>
+            <div className='flex flex-col gap-y-2 border rounded mb-2'>
+              <div className='p-2'>
+                <div className='flex items-center space-x-3'>
+                  <span className='text-sm font-medium text-gray-600'>
+                    Status
+                  </span>
+                  <Swiper
+                    spaceBetween={10}
+                    slidesPerView={5.25}
+                    className='w-full h-8'
                   >
-                    <option value=''>Pilih Site</option>
-                    {listSites.map((site) => (
-                      <option value={site} key={site}>
-                        {site}
-                      </option>
+                    {statuses.map((status) => (
+                      <SwiperSlide key={status.id} className='w-auto'>
+                        <button
+                          className={`px-4 py-1 text-sm font-medium border rounded-lg transition whitespace-nowrap min-w-40
+                  ${
+                    statusNew === status.id
+                      ? 'border-red-500 text-red-500 bg-white'
+                      : 'border-gray-300 text-gray-400 bg-gray-100 hover:bg-gray-200'
+                  }`}
+                          onClick={() => handleStatusChange(status.id)}
+                        >
+                          {status.label}
+                        </button>
+                      </SwiperSlide>
                     ))}
-                  </select>
-                ) : (
-                  <div></div>
-                )}
+                  </Swiper>
+                </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 ? (
+                    <select
+                      value={siteFilter}
+                      onChange={handleSiteFilterChange}
+                      className='form-input'
+                    >
+                      <option value=''>Pilih Site</option>
+                      {listSites.map((site) => (
+                        <option value={site} key={site}>
+                          {site}
+                        </option>
+                      ))}
+                    </select>
+                  ) : (
+                    <div></div>
+                  )}
 
-                <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'
+                  <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 className='flex flex-row gap-4 items-center justify-center'>
+                  <p>
+                    Menampilkan {startItem}-
+                    {endItem
+                      ? endItem
+                      : transactions?.data?.saleOrderTotal
+                      ? transactions?.data?.saleOrderTotal
+                      : limitNew}{' '}
+                    dari{' '}
+                    {transactions?.data?.saleOrderTotal
+                      ? transactions?.data?.saleOrderTotal
+                      : limitNew}
+                  </p>
+                  <select
+                    id='limitSelect'
+                    value={limitNew}
+                    onChange={(e) => {
+                      setLimitNew(Number(e.target.value));
+                      setPageNew(1);
+                    }}
+                    className='border p-2'
                   >
-                    <MagnifyingGlassIcon className='w-6' />
-                  </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>
+                    <option value={10}>10</option>
+                    <option value={15}>15</option>
+                    <option value={20}>20</option>
+                  </select>
+                </div>
               </div>
             </div>
-            <div className='flex'>
+            <div className='flex justify-center items-center'>
               {!transactions.isLoading &&
-                (!transactions?.data?.saleOrders ||
-                  transactions?.data?.saleOrders?.length == 0) && (
+                transactions?.data?.saleOrders?.length == 0 && (
                   <div className='justify-center p-4'>
                     <p className='text-gray-500 text-center '>
                       Tidak Ada Transaksi
@@ -512,107 +668,138 @@ const Transactions = ({ context = '' }) => {
                   </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:{' '}
-                            {
+              {transactions.isLoading && (
+                <div className='flex justify-center items-center my-2'>
+                  <Spinner className='w-6 text-gray_r-12/50 fill-gray_r-12' />
+                </div>
+              )}
+
+              {!transactions.isLoading &&
+                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 className='text-black'>
+                                Salesperson:{' '}
+                                {
+                                  <span className='font-semibold'>
+                                    {saleOrder.sales}
+                                  </span>
+                                }
+                              </p>
+                            </div>
+                            <div className='text-black'>
+                              Tanggal Pesanan:{' '}
                               <span className='font-semibold'>
-                                {saleOrder.sales}
+                                {saleOrder.dateOrder.split(' ')[0] || '-'}
                               </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>
+                          <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'>
+                                <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 text-black'>
+                                      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, 6)
+                                          .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 text-black'>
+                                <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/4 flex flex-row gap-3 justify-center items-center'>
+                              <div className='flex flex-col text-black'>
+                                <p>Total Harga</p>
+                                <p className='font-bold'>
+                                  {currencyFormat(saleOrder.amountTotal)}
+                                </p>
+                              </div>
+                              <div>
+                                <button
+                                  type='button'
+                                  onClick={() =>
+                                    handleBuyBack(saleOrder.products)
+                                  }
+                                  className='flex-1 py-2 btn-solid-red text-nowrap'
+                                >
+                                  Beli Lagi
+                                </button>
                               </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>
+                        </Link>
                       </div>
-                      {/* </Link> */}
-                    </div>
-                  ))}
-                </div>
-              )}
+                    ))}
+                  </div>
+                )}
             </div>
-            <table className='table-data'>
+            {/* <table className='table-data'>
               <thead>
                 <tr>
                   <th>No. Transaksi</th>
@@ -670,7 +857,7 @@ const Transactions = ({ context = '' }) => {
                   </tr>
                 ))}
               </tbody>
-            </table>
+            </table> */}
 
             <Pagination
               pageCount={pageCount}
-- 
cgit v1.2.3


From 781eb7fca4c0b82d7e531a56c1d939de7bb4d399 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Tue, 4 Mar 2025 13:37:16 +0700
Subject: <iman> add mobile

---
 src/lib/transaction/components/Transactions.jsx | 213 ++++++++++++++++++++----
 1 file changed, 177 insertions(+), 36 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 64ae9393..2ef50dcb 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -53,8 +53,6 @@ const Transactions = ({ context = '' }) => {
     isLoading,
     setIsloading,
   } = useProductCartContext();
-  console.log('context', context);
-  console.log('router.query', router.query);
   const [inputQuery, setInputQuery] = useState(q);
   const [toOthers, setToOthers] = useState(null);
   const [toCancel, setToCancel] = useState(null);
@@ -86,9 +84,7 @@ const Transactions = ({ context = '' }) => {
     { id: 'cancel', label: 'Pesanan Dibatalkan' },
   ];
 
-  console.log('query', query);
   const { transactions } = useTransactions({ query });
-  // console.log('transactions', transactions);
   const fetchSite = async () => {
     const site = await getSite();
     setListSites(site.sites);
@@ -285,8 +281,6 @@ const Transactions = ({ context = '' }) => {
         )
       );
 
-      // console.log(`Produk berhasil dimasukkan ke dalam cart`, results);
-
       // ✅ Panggil setRefreshCart(true) setiap kali satu produk berhasil ditambahkan
 
       setRefreshCart(true);
@@ -322,6 +316,8 @@ const Transactions = ({ context = '' }) => {
 
     if (status === 'all') {
       router.push('/my/transactions');
+    } else {
+      setPageNew(1);
     }
   };
 
@@ -329,18 +325,85 @@ const Transactions = ({ context = '' }) => {
     <>
       <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 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 className='grid grid-cols-3 justify-between items-center gap-2 w-full '>
+            <select
+              value={statusNew}
+              onChange={(e) => handleStatusChange(e.target.value)}
+              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
+            >
+              {statuses.map((status) => (
+                <option key={status.id} value={status.id}>
+                  {status.label}
+                </option>
+              ))}
+            </select>
+            <select
+              value={statusNew}
+              onChange={(e) => handleStatusChange(e.target.value)}
+              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
+            >
+              {statuses.map((status) => (
+                <option key={status.id} value={status.id}>
+                  {status.label}
+                </option>
+              ))}
+            </select>
+            <select
+              value={statusNew}
+              onChange={(e) => setStatusNew(e.target.value)}
+              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
+            >
+              {statuses.map((status) => (
+                <option key={status.id} value={status.id}>
+                  {status.label}
+                </option>
+              ))}
+            </select>
+          </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'
+                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>
+                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'
+              >
+                <option value={10}>10</option>
+                <option value={15}>15</option>
+                <option value={20}>20</option>
+              </select>
+            </div>
+          </div>
 
           {transactions.isLoading && (
             <div className='flex justify-center my-4'>
@@ -357,15 +420,15 @@ const Transactions = ({ context = '' }) => {
 
           {transactions.data?.saleOrders?.map((saleOrder, index) => (
             <div
-              className='p-4 shadow border border-gray_r-3 rounded-md'
+              className='p-4 shadow border border-gray_r-3 text-xs rounded-md flex flex-col gap-2'
               key={index}
             >
-              <div className='grid grid-cols-2'>
+              <div className='flex flex-row justify-between items-start'>
                 <Link href={`${router.pathname}/${saleOrder.id}`}>
-                  <span className='text-caption-2 text-gray_r-11'>
-                    No. Transaksi
+                  <h2 className='text-danger-500'>{saleOrder.name}</h2>
+                  <span className='font-medium text-black opacity-75'>
+                    {saleOrder.dateOrder.split(' ')[0] || '-'}
                   </span>
-                  <h2 className='text-danger-500 mt-1'>{saleOrder.name}</h2>
                 </Link>
                 <div className='flex gap-x-1 justify-end'>
                   <TransactionStatusBadge status={saleOrder.status} />
@@ -375,8 +438,85 @@ const Transactions = ({ context = '' }) => {
                   />
                 </div>
               </div>
-              <Link href={`${router.pathname}/${saleOrder.id}`}>
-                <div className='grid grid-cols-2 mt-3'>
+              <div className='col-span-2 h-[1px] w-full bg-gray-300'></div>
+              <Link
+                href={`${router.pathname}/${saleOrder.id}`}
+                className='flex flex-col gap-2'
+              >
+                <div className='flex flex-row gap-2'>
+                  <div className='flex w-1/5'>
+                    <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 w-4/5 flex-col gap-2 justify-start'>
+                    <p className='flex flex-row gap-2'>
+                      <span className=' text-black'>Nomor PO:</span>
+                      <span className=' 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 truncate text-sm'>
+                      {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, 6)
+                            .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-red-500 text-nowrap'
+                          >
+                            Lihat semua produk
+                          </Link>
+                        </div>
+                      )}
+                    </div>
+                    <div className='flex flex-row w-full text-nowrap gap-2 text-black'>
+                      <span className=''>Pesanan dibuat oleh:</span>
+                      <p className=' font-semibold truncate'>
+                        {saleOrder.address.customer?.name || '-'}
+                      </p>
+                    </div>
+                  </div>
+                </div>
+                <div className='col-span-2 h-[1px] w-full bg-gray-300'></div>
+                <div className='flex flex-row gap-3 justify-between items-center text-sm'>
+                  <div className='flex flex-col text-black'>
+                    <p>Total Harga</p>
+                    <p className='font-bold'>
+                      {currencyFormat(saleOrder.amountTotal)}
+                    </p>
+                  </div>
+                  <div>
+                    <button
+                      type='button'
+                      onClick={() => handleBuyBack(saleOrder.products)}
+                      className='flex-1 py-2 btn-solid-red text-nowrap'
+                    >
+                      Beli Lagi
+                    </button>
+                  </div>
+                </div>
+
+                {/* <div className='grid grid-cols-2 mt-3'>
                   <div>
                     <span className='text-caption-2 text-gray_r-11'>
                       No. Purchase Order
@@ -393,8 +533,8 @@ const Transactions = ({ context = '' }) => {
                       {saleOrder.invoiceCount} Invoice
                     </p>
                   </div>
-                </div>
-                <div className='grid grid-cols-2 mt-3'>
+                </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'>
@@ -409,15 +549,16 @@ const Transactions = ({ context = '' }) => {
                       {currencyFormat(saleOrder.amountTotal)}
                     </p>
                   </div>
-                </div>
+                </div> */}
               </Link>
             </div>
           ))}
 
           <Pagination
             pageCount={pageCount}
-            currentPage={parseInt(page)}
-            url={router.pathname + pageQuery}
+            currentPage={parseInt(pageNew)}
+            // url={router.pathname + pageQuery}
+            url={`/my/transactions?${toQuery(_.omit(query, ['page']))}`}
             className='mt-2 mb-2'
           />
 
@@ -568,7 +709,7 @@ const Transactions = ({ context = '' }) => {
             <div className='flex flex-col gap-y-2 border rounded mb-2'>
               <div className='p-2'>
                 <div className='flex items-center space-x-3'>
-                  <span className='text-sm font-medium text-gray-600'>
+                  <span className='text-base font-semibold text-gray-600'>
                     Status
                   </span>
                   <Swiper
@@ -636,11 +777,11 @@ const Transactions = ({ context = '' }) => {
                       ? endItem
                       : transactions?.data?.saleOrderTotal
                       ? transactions?.data?.saleOrderTotal
-                      : limitNew}{' '}
+                      : limitNew * pageNew}{' '}
                     dari{' '}
                     {transactions?.data?.saleOrderTotal
                       ? transactions?.data?.saleOrderTotal
-                      : limitNew}
+                      : limitNew * pageNew}
                   </p>
                   <select
                     id='limitSelect'
@@ -684,7 +825,7 @@ const Transactions = ({ context = '' }) => {
                         className='border p-2 hover:border-red-500 w-full rounded-sm'
                       >
                         <Link
-                          href={`/my/quotations/${saleOrder?.id}`}
+                          href={`/my/transactions/${saleOrder?.id}`}
                           className='hover:border-red-500 block w-full'
                         >
                           <div className='flex flex-row justify-between items-center py-2'>
@@ -713,7 +854,7 @@ const Transactions = ({ context = '' }) => {
                           <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'>
-                                <div>
+                                <div className='min-w-36 max-w-36'>
                                   <Image
                                     src={saleOrder.products[0]?.parent?.image}
                                     alt={saleOrder.products[0]?.name}
@@ -749,7 +890,7 @@ const Transactions = ({ context = '' }) => {
                                               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'
+                                              className='object-contain object-center border border-gray_r-6 h-16 w-16 rounded-md'
                                             />
                                           ))}
                                         <Link
-- 
cgit v1.2.3


From e38dff05fd629ef054d571e7d3b066f1bdd5520b Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Mon, 10 Mar 2025 11:21:46 +0700
Subject: <iman> add sort filter

---
 src/lib/transaction/components/Transactions.jsx | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 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 2ef50dcb..a6cfe177 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -44,6 +44,7 @@ const Transactions = ({ context = '' }) => {
     site = null,
     limit = 15,
     status = 'all',
+    sort = 'none',
   } = router.query;
   const {
     productCart,
@@ -63,6 +64,7 @@ const Transactions = ({ context = '' }) => {
   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 query = {
     name: q,
@@ -70,6 +72,7 @@ const Transactions = ({ context = '' }) => {
     context: contextNew,
     limit: limitNew,
     status: statusNew,
+    sort: sortNew,
     site:
       siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
   };
@@ -84,6 +87,12 @@ const Transactions = ({ context = '' }) => {
     { id: 'cancel', label: 'Pesanan Dibatalkan' },
   ];
 
+  const sortes = [
+    { id: 'none', label: 'Urutkan' },
+    { id: 'asc', label: 'dari yang terkecil' },
+    { id: 'desc', label: 'dari yang terbesar' },
+  ];
+
   const { transactions } = useTransactions({ query });
   const fetchSite = async () => {
     const site = await getSite();
@@ -338,11 +347,11 @@ const Transactions = ({ context = '' }) => {
               ))}
             </select>
             <select
-              value={statusNew}
-              onChange={(e) => handleStatusChange(e.target.value)}
+              value={sortNew}
+              onChange={(e) => setSortNew(e.target.value)}
               className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
             >
-              {statuses.map((status) => (
+              {sortes.map((status) => (
                 <option key={status.id} value={status.id}>
                   {status.label}
                 </option>
-- 
cgit v1.2.3


From 0fada18346571b321ceb46689659b544ffc9dfe2 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Wed, 12 Mar 2025 09:38:31 +0700
Subject: <iman> fix transaction

---
 src/lib/transaction/components/Transactions.jsx | 227 +++++++++++++++++++++---
 1 file changed, 198 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 a6cfe177..d93c9aef 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -35,6 +35,13 @@ import { upsertUserCart } from '~/services/cart';
 import { useProductCartContext } from '@/contexts/ProductCartContext';
 import { Swiper, SwiperSlide } from 'swiper/react';
 import 'swiper/css';
+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';
 const Transactions = ({ context = '' }) => {
   const auth = useAuth();
   const router = useRouter();
@@ -45,6 +52,8 @@ const Transactions = ({ context = '' }) => {
     limit = 15,
     status = 'all',
     sort = 'none',
+    startDate = null,
+    endDate = new Date(),
   } = router.query;
   const {
     productCart,
@@ -66,6 +75,40 @@ const Transactions = ({ context = '' }) => {
   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 parseDate = (date) => {
+    console.log('masuk sini', date);
+    if (null || 'null') return null;
+    if (!date) return null;
+    if (date instanceof Date) return date; // Jika sudah Date, langsung return
+    const [day, month, year] = date.split('/').map(Number);
+    return new Date(year, month - 1, day);
+  };
+
+  const [state, setState] = useState([
+    {
+      startDate: startDate != null || 'null' ? parseDate(startDate) : null, // Gunakan `parseDate`
+      endDate: startDate == null ? endDate : parseDate(endDate),
+      key: 'selection',
+    },
+  ]);
+  console.log('startDate', startDate);
+  console.log('state', state);
+  // useEffect(() => {
+  //   if (state[0].startDate != null) {
+  //     setState([
+  //       {
+  //         startDate: parseDate(startDate),
+  //         endDate: parseDate(endDate),
+  //         key: 'selection',
+  //       },
+  //     ]);
+  //   }
+  // }, [startDate, endDate]);
+
   const query = {
     name: q,
     offset: (pageNew - 1) * limitNew,
@@ -73,10 +116,13 @@ const Transactions = ({ context = '' }) => {
     limit: limitNew,
     status: statusNew,
     sort: sortNew,
+    startDate: state[0].startDate
+      ? state[0].startDate.toLocaleDateString('id-ID')
+      : state[0].startDate,
+    endDate: state[0]?.endDate?.toLocaleDateString('id-ID'),
     site:
       siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
   };
-
   const statuses = [
     { id: 'all', label: 'Semua' },
     { id: 'quotation', label: 'Pending Quotation' },
@@ -92,7 +138,6 @@ 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();
@@ -330,15 +375,47 @@ const Transactions = ({ context = '' }) => {
     }
   };
 
+  const handleReset = () => {
+    setState([
+      {
+        startDate: null,
+        endDate: new Date(),
+        key: 'selection',
+      },
+    ]);
+    setIsOpenCalender(false);
+    router.push('/my/transactions');
+  };
+
+  const formatDate = (dateString) => {
+    const months = [
+      'Januari',
+      'Februari',
+      'Maret',
+      'April',
+      'Mei',
+      'Juni',
+      'Juli',
+      'Agustus',
+      'September',
+      'Oktober',
+      'November',
+      'Desember',
+    ];
+
+    const [day, month, year] = dateString.split('/');
+    return `${day} ${months[parseInt(month, 10) - 1]} ${year}`;
+  };
+
   return (
     <>
       <MobileView>
         <div className='p-4 flex flex-col gap-y-4'>
-          <div className='grid grid-cols-3 justify-between items-center gap-2 w-full '>
+          <div className='grid grid-cols-[30%_30%_40%] justify-between items-center gap-2 w-full '>
             <select
               value={statusNew}
               onChange={(e) => handleStatusChange(e.target.value)}
-              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
+              className='border border-gray-300 rounded-lg px-2 py-1 text-xs bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
             >
               {statuses.map((status) => (
                 <option key={status.id} value={status.id}>
@@ -349,7 +426,7 @@ const Transactions = ({ context = '' }) => {
             <select
               value={sortNew}
               onChange={(e) => setSortNew(e.target.value)}
-              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
+              className='border border-gray-300 rounded-lg px-2 py-1 text-xs bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
             >
               {sortes.map((status) => (
                 <option key={status.id} value={status.id}>
@@ -357,17 +434,99 @@ const Transactions = ({ context = '' }) => {
                 </option>
               ))}
             </select>
-            <select
-              value={statusNew}
-              onChange={(e) => setStatusNew(e.target.value)}
-              className='border border-gray-300 rounded-lg px-3 py-1 text-sm bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500'
-            >
-              {statuses.map((status) => (
-                <option key={status.id} value={status.id}>
-                  {status.label}
-                </option>
-              ))}
-            </select>
+            <div className='relative w-full text-xs'>
+              <div
+                className='border border-gray-300 rounded-lg bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500 w-full px-2 py-1 flex items-center justify-between cursor-pointer'
+                onClick={() => setIsOpenCalender(true)}
+              >
+                <span className='text-nowrap px-1 truncate'>
+                  {state[0]?.startDate
+                    ? `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
+                    : 'Semua Tanggal'}
+                </span>
+              </div>
+
+              {isOpenCalender && (
+                <div className='fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50'>
+                  <div className='calendar-container bg-white shadow-lg border rounded-lg p-4  w-full'>
+                    <DateRangePicker
+                      onChange={(item) => setState([item.selection])}
+                      showSelectionPreview={true}
+                      maxDate={new Date()}
+                      moveRangeOnFirstSelection={false}
+                      months={1}
+                      ranges={state}
+                      direction='horizontal'
+                      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>
+                    <div className='flex flex-row justify-end gap-3 mt-2'>
+                      <button
+                        className='px-4 py-1 bg-gray-500 text-white rounded'
+                        onClick={() => setIsOpenCalender(false)}
+                      >
+                        Done
+                      </button>
+                      <button
+                        className='px-4 py-1 bg-red-500 text-white rounded'
+                        onClick={handleReset}
+                      >
+                        Reset
+                      </button>
+                    </div>
+                  </div>
+                </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}>
@@ -379,14 +538,14 @@ const Transactions = ({ context = '' }) => {
               </button>
               <input
                 type='text'
-                className='form-input border-l-0 rounded-l-none'
+                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>
+              <p className='text-xs'>
                 Menampilkan {startItem}-
                 {endItem
                   ? endItem
@@ -405,7 +564,7 @@ const Transactions = ({ context = '' }) => {
                   setLimitNew(Number(e.target.value));
                   setPageNew(1);
                 }}
-                className='border p-2'
+                className='border p-2 text-xs'
               >
                 <option value={10}>10</option>
                 <option value={15}>15</option>
@@ -436,7 +595,7 @@ const Transactions = ({ context = '' }) => {
                 <Link href={`${router.pathname}/${saleOrder.id}`}>
                   <h2 className='text-danger-500'>{saleOrder.name}</h2>
                   <span className='font-medium text-black opacity-75'>
-                    {saleOrder.dateOrder.split(' ')[0] || '-'}
+                    {formatDate(saleOrder.dateOrder.split(' ')[0]) || '-'}
                   </span>
                 </Link>
                 <div className='flex gap-x-1 justify-end'>
@@ -493,7 +652,11 @@ const Transactions = ({ context = '' }) => {
                             href={`/my/quotations/${saleOrder?.id}`}
                             className=' text-red-500 text-nowrap'
                           >
-                            Lihat semua produk
+                            {saleOrder.products?.length > 6
+                              ? 'Lihat ' +
+                                (saleOrder.products?.length - 6) +
+                                ' produk lainnya'
+                              : 'Lihat semua produk'}
                           </Link>
                         </div>
                       )}
@@ -508,9 +671,9 @@ const Transactions = ({ context = '' }) => {
                 </div>
                 <div className='col-span-2 h-[1px] w-full bg-gray-300'></div>
                 <div className='flex flex-row gap-3 justify-between items-center text-sm'>
-                  <div className='flex flex-col text-black'>
-                    <p>Total Harga</p>
-                    <p className='font-bold'>
+                  <div className='flex flex-col text-black text-xs'>
+                    <p className='font-extralight'>Total Harga</p>
+                    <p className='font-semibold'>
                       {currencyFormat(saleOrder.amountTotal)}
                     </p>
                   </div>
@@ -715,7 +878,7 @@ const Transactions = ({ context = '' }) => {
                 </div>
               </div>
             </div>
-            <div className='flex flex-col gap-y-2 border rounded mb-2'>
+            <div className='flex flex-col gap-y-2  border rounded-lg mb-2'>
               <div className='p-2'>
                 <div className='flex items-center space-x-3'>
                   <span className='text-base font-semibold text-gray-600'>
@@ -723,7 +886,7 @@ const Transactions = ({ context = '' }) => {
                   </span>
                   <Swiper
                     spaceBetween={10}
-                    slidesPerView={5.25}
+                    slidesPerView={5.8}
                     className='w-full h-8'
                   >
                     {statuses.map((status) => (
@@ -831,7 +994,7 @@ const Transactions = ({ context = '' }) => {
                     {transactions.data.saleOrders.map((saleOrder, index) => (
                       <div
                         key={index}
-                        className='border p-2 hover:border-red-500 w-full rounded-sm'
+                        className='border py-2 px-4 hover:border-red-500 w-full rounded-lg'
                       >
                         <Link
                           href={`/my/transactions/${saleOrder?.id}`}
@@ -855,7 +1018,9 @@ const Transactions = ({ context = '' }) => {
                             <div className='text-black'>
                               Tanggal Pesanan:{' '}
                               <span className='font-semibold'>
-                                {saleOrder.dateOrder.split(' ')[0] || '-'}
+                                {formatDate(
+                                  saleOrder.dateOrder.split(' ')[0]
+                                ) || '-'}
                               </span>
                             </div>
                           </div>
@@ -906,7 +1071,11 @@ const Transactions = ({ context = '' }) => {
                                           href={`/my/quotations/${saleOrder?.id}`}
                                           className='text-sm text-red-500 text-nowrap'
                                         >
-                                          Lihat semua produk
+                                          {saleOrder.products?.length > 6
+                                            ? 'Lihat ' +
+                                              (saleOrder.products?.length - 6) +
+                                              ' produk lainnya'
+                                            : 'Lihat semua produk'}
                                         </Link>
                                       </div>
                                     )}
-- 
cgit v1.2.3


From b4a595eaa8600e7bd1bafcef38abe4c01a5b664c Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Wed, 12 Mar 2025 16:59:18 +0700
Subject: <iman> fix transaction

---
 src/lib/transaction/components/Transactions.jsx | 28 +++++++------------------
 1 file changed, 7 insertions(+), 21 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 d93c9aef..ece97734 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -80,7 +80,6 @@ const Transactions = ({ context = '' }) => {
   const [isOpenCalender, setIsOpenCalender] = useState(false);
 
   const parseDate = (date) => {
-    console.log('masuk sini', date);
     if (null || 'null') return null;
     if (!date) return null;
     if (date instanceof Date) return date; // Jika sudah Date, langsung return
@@ -95,19 +94,6 @@ const Transactions = ({ context = '' }) => {
       key: 'selection',
     },
   ]);
-  console.log('startDate', startDate);
-  console.log('state', state);
-  // useEffect(() => {
-  //   if (state[0].startDate != null) {
-  //     setState([
-  //       {
-  //         startDate: parseDate(startDate),
-  //         endDate: parseDate(endDate),
-  //         key: 'selection',
-  //       },
-  //     ]);
-  //   }
-  // }, [startDate, endDate]);
 
   const query = {
     name: q,
@@ -369,7 +355,7 @@ const Transactions = ({ context = '' }) => {
     }
 
     if (status === 'all') {
-      router.push('/my/transactions');
+      router.push(`${router.pathname}`);
     } else {
       setPageNew(1);
     }
@@ -384,7 +370,7 @@ const Transactions = ({ context = '' }) => {
       },
     ]);
     setIsOpenCalender(false);
-    router.push('/my/transactions');
+    router.push(`${router.pathname}`);
   };
 
   const formatDate = (dateString) => {
@@ -649,7 +635,7 @@ const Transactions = ({ context = '' }) => {
                               />
                             ))}
                           <Link
-                            href={`/my/quotations/${saleOrder?.id}`}
+                            href={`${router.pathname}/${saleOrder?.id}`}
                             className=' text-red-500 text-nowrap'
                           >
                             {saleOrder.products?.length > 6
@@ -730,7 +716,7 @@ const Transactions = ({ context = '' }) => {
             pageCount={pageCount}
             currentPage={parseInt(pageNew)}
             // url={router.pathname + pageQuery}
-            url={`/my/transactions?${toQuery(_.omit(query, ['page']))}`}
+            url={`${router.pathname}?${toQuery(_.omit(query, ['page']))}`}
             className='mt-2 mb-2'
           />
 
@@ -997,7 +983,7 @@ const Transactions = ({ context = '' }) => {
                         className='border py-2 px-4 hover:border-red-500 w-full rounded-lg'
                       >
                         <Link
-                          href={`/my/transactions/${saleOrder?.id}`}
+                          href={`${router.pathname}/${saleOrder?.id}`}
                           className='hover:border-red-500 block w-full'
                         >
                           <div className='flex flex-row justify-between items-center py-2'>
@@ -1068,7 +1054,7 @@ const Transactions = ({ context = '' }) => {
                                             />
                                           ))}
                                         <Link
-                                          href={`/my/quotations/${saleOrder?.id}`}
+                                          href={`${router.pathname}/${saleOrder?.id}`}
                                           className='text-sm text-red-500 text-nowrap'
                                         >
                                           {saleOrder.products?.length > 6
@@ -1182,7 +1168,7 @@ const Transactions = ({ context = '' }) => {
               pageCount={pageCount}
               currentPage={parseInt(pageNew)}
               // url={router.pathname + (pageQuery ? `?${pageQuery}` : '')}
-              url={`/my/transactions?${toQuery(_.omit(query, ['page']))}`}
+              url={`${router.pathname}?${toQuery(_.omit(query, ['page']))}`}
               className='mt-2 mb-2'
             />
           </div>
-- 
cgit v1.2.3


From 1e2c20a9871bf0a6117ae63d1e8d9d20119460ed Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Thu, 13 Mar 2025 10:07:38 +0700
Subject: <iman> update code

---
 src/lib/transaction/components/Transactions.jsx | 4 ++--
 1 file changed, 2 insertions(+), 2 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 ece97734..45821901 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -1021,7 +1021,7 @@ const Transactions = ({ context = '' }) => {
                                     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'>
+                                <div className='flex flex-col gap-3 justify-start truncate w-full'>
                                   <p className='flex flex-row gap-2'>
                                     <span className='text-sm text-black'>
                                       Nomor PO:
@@ -1030,7 +1030,7 @@ const Transactions = ({ context = '' }) => {
                                       {saleOrder.purchaseOrderName || '-'}
                                     </span>
                                   </p>
-                                  <p className='line-clamp-2 leading-6 tracking-wide opacity-90 !text-gray_r-12 font-semibold text-nowrap'>
+                                  <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'>
-- 
cgit v1.2.3


From 0d28dc8ff5fb8c5399e356ed6ecae4fce2019ca6 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Sat, 31 May 2025 08:55:43 +0700
Subject: <hafid> fix repeat-order

---
 src/lib/transaction/components/Transactions.jsx | 124 +++++++++++++++++++++---
 1 file changed, 110 insertions(+), 14 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 45821901..c4651119 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -78,6 +78,8 @@ const Transactions = ({ 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 parseDate = (date) => {
     if (null || 'null') return null;
@@ -263,7 +265,16 @@ const Transactions = ({ context = '' }) => {
   const getAllData = async () => {
     const query = {
       name: q,
-      context,
+      offset: (pageNew - 1) * limitNew,
+      limit: limitNew,
+      context: contextMap[statusNew], // gunakan contextMap
+      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),
     };
@@ -345,22 +356,29 @@ const Transactions = ({ context = '' }) => {
     }
   };
 
-  const handleStatusChange = (status) => {
+  
+  const handleStatusChange = async (status) => {
     setStatusNew(status);
+    setPageNew(1);
 
-    if (['quotation', 'cancel', 'diterima', ''].includes(status)) {
-      setcontextNew('quotation');
-    } else {
-      setcontextNew('');
+    if (status === 'all' && cachedAllData) {
+      setCurrentData(cachedAllData); 
+      return; 
     }
-
+    const data = await fetchSite(status, 1);
+    
     if (status === 'all') {
-      router.push(`${router.pathname}`);
-    } else {
-      setPageNew(1);
+      setCachedAllData(data);
     }
+
+    setCurrentData(data);
   };
 
+  useEffect(() => {
+    setCachedAllData([]);
+  }, []);
+
+
   const handleReset = () => {
     setState([
       {
@@ -857,9 +875,7 @@ const Transactions = ({ context = '' }) => {
                 <div className='text-justify flex flex-col gap-1'>
                   <p className='font-bold text-black'>Info Transaksi</p>
                   <span className='text-black'>
-                    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
-                    do eiusmod tempor incididunt ut labore et dolore magna
-                    aliqua.
+                    Gunakan filter status untuk mempermudah pencarian transaksi anda di Daftar Transaksi
                   </span>
                 </div>
               </div>
@@ -928,6 +944,86 @@ const Transactions = ({ context = '' }) => {
                     </button>
                   </form>
                 </div>
+                <div className='flex flex-col gap-2 pb-2'>
+                  <button
+                    type='button'
+                    className='form-input btn py-4 mt-1 cursor-pointer hover:bg-gray-100 rounded transition duration-150 ease-in-out text-left w-full'
+                    onClick={() => setIsOpenCalender(true)}
+                  >
+                    <span className='text-nowrap px-1 truncate'>
+                      {state[0]?.startDate
+                        ? `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
+                        : 'Filter By Tanggal'}
+                    </span>
+                  </button>
+                  {isOpenCalender && (
+                  <div className='absolute mt-2 bg-white p-4 rounded shadow-lg'>
+                    {/* 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'
+                    >
+                      &times;
+                    </button>
+                    <DateRangePicker
+                      onChange={(item) => setState([item.selection])}
+                      showSelectionPreview={true}
+                      maxDate={new Date()}
+                      moveRangeOnFirstSelection={false}
+                      months={1}
+                      ranges={state}
+                      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>
+                    <div className='flex flex-row justify-end gap-3 mt-2'>
+                      <button
+                        className='px-4 py-1 bg-gray-500 text-white rounded'
+                        onClick={() => setIsOpenCalender(false)}
+                      >
+                        Done
+                      </button>
+                      <button
+                        className='px-4 py-1 bg-red-500 text-white rounded'
+                        onClick={handleReset}
+                      >
+                        Reset
+                      </button>
+                    </div>
+                  </div>
+                )}
+                </div>
                 <div className='flex flex-row gap-4 items-center justify-center'>
                   <p>
                     Menampilkan {startItem}-
@@ -980,7 +1076,7 @@ const Transactions = ({ context = '' }) => {
                     {transactions.data.saleOrders.map((saleOrder, index) => (
                       <div
                         key={index}
-                        className='border py-2 px-4 hover:border-red-500 w-full rounded-lg'
+                        className='border py-2 px-4 hover:border-red-500 w-full rounded-lg data-item'
                       >
                         <Link
                           href={`${router.pathname}/${saleOrder?.id}`}
-- 
cgit v1.2.3


From 04961a55929017f77ee6801d2b7ada4c05689821 Mon Sep 17 00:00:00 2001
From: it-fixcomart <it@fixcomart.co.id>
Date: Thu, 31 Jul 2025 15:55:05 +0700
Subject: <hafid> fix repeat order

---
 src/lib/transaction/components/Transactions.jsx | 461 +++++++++++++-----------
 1 file changed, 258 insertions(+), 203 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 c4651119..acb925da 100644
--- a/src/lib/transaction/components/Transactions.jsx
+++ b/src/lib/transaction/components/Transactions.jsx
@@ -1,5 +1,5 @@
 import { useRouter } from 'next/router';
-import { useEffect, useState } from 'react';
+import { useEffect, useState, useRef  } from 'react';
 import { toast } from 'react-hot-toast';
 import {
   EllipsisVerticalIcon,
@@ -34,7 +34,10 @@ import Image from '@/core/components/elements/Image/Image';
 import { upsertUserCart } from '~/services/cart';
 import { useProductCartContext } from '@/contexts/ProductCartContext';
 import { Swiper, SwiperSlide } from 'swiper/react';
+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';
@@ -45,6 +48,7 @@ import { Popover } from '@headlessui/react';
 const Transactions = ({ context = '' }) => {
   const auth = useAuth();
   const router = useRouter();
+  const swiperRef = useRef(null);
   const {
     q = '',
     page = 1,
@@ -80,11 +84,12 @@ const Transactions = ({ context = '' }) => {
   const [isOpenCalender, setIsOpenCalender] = useState(false);
   const [cachedAllData, setCachedAllData] = useState(null); // Simpan data "All"
   const [currentData, setCurrentData] = useState([]);     // Data yang ditampilkan
+  const calendarRef = useRef(null);
+  const [isDateSelected, setIsDateSelected] = useState(false);
 
   const parseDate = (date) => {
-    if (null || 'null') return null;
-    if (!date) return null;
-    if (date instanceof Date) return date; // Jika sudah Date, langsung return
+    if (!date || date === 'null') return null;
+    if (date instanceof Date) return date;
     const [day, month, year] = date.split('/').map(Number);
     return new Date(year, month - 1, day);
   };
@@ -106,7 +111,7 @@ const Transactions = ({ context = '' }) => {
     sort: sortNew,
     startDate: state[0].startDate
       ? state[0].startDate.toLocaleDateString('id-ID')
-      : state[0].startDate,
+      : null,
     endDate: state[0]?.endDate?.toLocaleDateString('id-ID'),
     site:
       siteFilter || (auth?.webRole === null && auth?.site ? auth.site : null),
@@ -114,8 +119,9 @@ const Transactions = ({ context = '' }) => {
   const statuses = [
     { id: 'all', label: 'Semua' },
     { id: 'quotation', label: 'Pending Quotation' },
-    { id: 'diterima', label: 'Pesanan Diterima' },
     { id: 'diproses', label: 'Pesanan Diproses' },
+    { id: 'dikemas', label: 'Pesanan Dikemas' },
+    { id: 'partial', label: 'Dikirim Sebagian' },
     { id: 'dikirim', label: 'Pesanan Dikirim' },
     { id: 'selesai', label: 'Pesanan Selesai' },
     { id: 'cancel', label: 'Pesanan Dibatalkan' },
@@ -302,6 +308,22 @@ const Transactions = ({ context = '' }) => {
     }
   };
 
+  useEffect(() => {
+    const handleClickOutside = (event) => {
+      if (
+        calendarRef.current &&
+        !calendarRef.current.contains(event.target)
+      ) {
+        setIsOpenCalender(false);
+      }
+    };
+
+    document.addEventListener("mousedown", handleClickOutside);
+    return () => {
+      document.removeEventListener("mousedown", handleClickOutside);
+    };
+  }, []);
+
   const startItem = 1 + (pageNew - 1) * limitNew;
   const endItem = Math.min(
     limitNew * pageNew,
@@ -438,82 +460,82 @@ const Transactions = ({ context = '' }) => {
                 </option>
               ))}
             </select>
-            <div className='relative w-full text-xs'>
-              <div
-                className='border border-gray-300 rounded-lg bg-white shadow-sm focus:outline-none focus:ring-2 focus:ring-red-500 w-full px-2 py-1 flex items-center justify-between cursor-pointer'
-                onClick={() => setIsOpenCalender(true)}
-              >
-                <span className='text-nowrap px-1 truncate'>
-                  {state[0]?.startDate
-                    ? `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
-                    : 'Semua Tanggal'}
-                </span>
-              </div>
-
-              {isOpenCalender && (
-                <div className='fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50'>
-                  <div className='calendar-container bg-white shadow-lg border rounded-lg p-4  w-full'>
-                    <DateRangePicker
-                      onChange={(item) => setState([item.selection])}
-                      showSelectionPreview={true}
-                      maxDate={new Date()}
-                      moveRangeOnFirstSelection={false}
-                      months={1}
-                      ranges={state}
-                      direction='horizontal'
-                      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>
-                    <div className='flex flex-row justify-end gap-3 mt-2'>
-                      <button
-                        className='px-4 py-1 bg-gray-500 text-white rounded'
-                        onClick={() => setIsOpenCalender(false)}
-                      >
-                        Done
-                      </button>
-                      <button
-                        className='px-4 py-1 bg-red-500 text-white rounded'
-                        onClick={handleReset}
-                      >
-                        Reset
-                      </button>
-                    </div>
+            <div ref={calendarRef} className="relative inline-block">
+                <button
+                  type='button'
+                  className='p-2 w-auto h-auto cursor-pointer hover:bg-gray-100 rounded transition duration-150 ease-in-out flex items-center justify-center'
+                  onClick={() => setIsOpenCalender((prev) => !prev)}
+                >
+                  <span className='text-nowrap px-1 truncate flex items-center gap-1'>
+                      {state[0]?.startDate ? (
+                        `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
+                      ) : (
+                        <Calendar size={16} className="text-gray-500" />
+                      )}
+                  </span>
+                </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'
+                  >
+                    &times;
+                  </button>
+                  <DateRangePicker
+                    onChange={(item) => setState([item.selection])}
+                    showSelectionPreview={false}
+                    maxDate={new Date()}
+                    moveRangeOnFirstSelection={false}
+                    months={1}
+                    ranges={state}
+                    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>
+                  <div className='flex flex-row justify-end gap-3 mt-2'>
+                    <button
+                      className='px-4 py-1 bg-red-500 text-white rounded'
+                      onClick={handleReset}
+                    >
+                      Reset
+                    </button>
                   </div>
                 </div>
-              )}
-            </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}
@@ -643,7 +665,7 @@ const Transactions = ({ context = '' }) => {
                       {saleOrder.products?.length > 1 && (
                         <div className='flex flex-row gap-1 justify-start items-center'>
                           {saleOrder.products
-                            .slice(1, 6)
+                            .slice(1, 4)
                             .map((product, index) => (
                               <Image
                                 key={index} // Tambahkan key untuk setiap elemen dalam map()
@@ -652,16 +674,21 @@ const Transactions = ({ context = '' }) => {
                                 className='object-contain object-center border border-gray_r-6 h-8 w-8 rounded-md'
                               />
                             ))}
-                          <Link
-                            href={`${router.pathname}/${saleOrder?.id}`}
-                            className=' text-red-500 text-nowrap'
-                          >
-                            {saleOrder.products?.length > 6
-                              ? 'Lihat ' +
-                                (saleOrder.products?.length - 6) +
-                                ' produk lainnya'
-                              : 'Lihat semua produk'}
-                          </Link>
+                          {saleOrder.products.length > 4 ? (
+                              <Link
+                                href={`${router.pathname}/${saleOrder?.id}`}
+                                className='text-red-500 text-nowrap'
+                              >
+                                +{saleOrder.products.length - 4} lihat semua produk
+                              </Link>
+                            ) : (
+                              <Link
+                                href={`${router.pathname}/${saleOrder?.id}`}
+                                className='text-red-500 text-nowrap'
+                              >
+                                Lihat semua produk
+                              </Link>
+                            )}
                         </div>
                       )}
                     </div>
@@ -880,33 +907,60 @@ const Transactions = ({ context = '' }) => {
                 </div>
               </div>
             </div>
-            <div className='flex flex-col gap-y-2  border rounded-lg mb-2'>
+            <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'>
                   <span className='text-base font-semibold text-gray-600'>
                     Status
                   </span>
-                  <Swiper
-                    spaceBetween={10}
-                    slidesPerView={5.8}
-                    className='w-full h-8'
-                  >
-                    {statuses.map((status) => (
-                      <SwiperSlide key={status.id} className='w-auto'>
-                        <button
-                          className={`px-4 py-1 text-sm font-medium border rounded-lg transition whitespace-nowrap min-w-40
-                  ${
-                    statusNew === status.id
-                      ? 'border-red-500 text-red-500 bg-white'
-                      : 'border-gray-300 text-gray-400 bg-gray-100 hover:bg-gray-200'
-                  }`}
-                          onClick={() => handleStatusChange(status.id)}
+                  <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" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
+                        </svg>
+                      </button>
+
+                      {/* Swiper container scrollable */}
+                      <div className="w-full overflow-hidden">
+                        <Swiper
+                          spaceBetween={10}
+                          slidesPerView="auto"
+                          className="status-swiper"
+                          modules={[Navigation]}
+                          navigation={{
+                            nextEl: '.custom-next',
+                            prevEl: '.custom-prev',
+                          }}
                         >
-                          {status.label}
-                        </button>
-                      </SwiperSlide>
-                    ))}
-                  </Swiper>
+                          {statuses.map((status) => (
+                            <SwiperSlide key={status.id} className="!w-auto">
+                              <button
+                                className={`px-4 py-1 text-sm font-medium border rounded-lg transition whitespace-nowrap
+                                  ${statusNew === status.id
+                                    ? 'border-red-500 text-red-500 bg-white'
+                                    : 'border-gray-300 text-gray-400 bg-gray-100 hover:bg-gray-200'
+                                  }`}
+                                onClick={() => handleStatusChange(status.id)}
+                              >
+                                {status.label}
+                              </button>
+                            </SwiperSlide>
+                          ))}
+                        </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" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
+                        </svg>
+                      </button>
+                    </div>
+                  </div>
                 </div>
               </div>
               <div className='flex flex-row items-center justify-between mb-2 p-2'>
@@ -944,86 +998,6 @@ const Transactions = ({ context = '' }) => {
                     </button>
                   </form>
                 </div>
-                <div className='flex flex-col gap-2 pb-2'>
-                  <button
-                    type='button'
-                    className='form-input btn py-4 mt-1 cursor-pointer hover:bg-gray-100 rounded transition duration-150 ease-in-out text-left w-full'
-                    onClick={() => setIsOpenCalender(true)}
-                  >
-                    <span className='text-nowrap px-1 truncate'>
-                      {state[0]?.startDate
-                        ? `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
-                        : 'Filter By Tanggal'}
-                    </span>
-                  </button>
-                  {isOpenCalender && (
-                  <div className='absolute mt-2 bg-white p-4 rounded shadow-lg'>
-                    {/* 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'
-                    >
-                      &times;
-                    </button>
-                    <DateRangePicker
-                      onChange={(item) => setState([item.selection])}
-                      showSelectionPreview={true}
-                      maxDate={new Date()}
-                      moveRangeOnFirstSelection={false}
-                      months={1}
-                      ranges={state}
-                      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>
-                    <div className='flex flex-row justify-end gap-3 mt-2'>
-                      <button
-                        className='px-4 py-1 bg-gray-500 text-white rounded'
-                        onClick={() => setIsOpenCalender(false)}
-                      >
-                        Done
-                      </button>
-                      <button
-                        className='px-4 py-1 bg-red-500 text-white rounded'
-                        onClick={handleReset}
-                      >
-                        Reset
-                      </button>
-                    </div>
-                  </div>
-                )}
-                </div>
                 <div className='flex flex-row gap-4 items-center justify-center'>
                   <p>
                     Menampilkan {startItem}-
@@ -1050,6 +1024,82 @@ const Transactions = ({ context = '' }) => {
                     <option value={15}>15</option>
                     <option value={20}>20</option>
                   </select>
+                  <div ref={calendarRef} className="relative inline-block">
+                    <button
+                      type='button'
+                      className='p-2 w-auto h-auto cursor-pointer border hover:bg-gray-100 rounded transition duration-150 ease-in-out flex items-center justify-center'
+                      onClick={() => setIsOpenCalender((prev) => !prev)}
+                    >
+                      <span className='text-nowrap px-1 truncate flex items-center gap-1'>
+                          {state[0]?.startDate ? (
+                            `${state[0].startDate.toLocaleDateString()} - ${state[0].endDate.toLocaleDateString()}`
+                          ) : (
+                            <Calendar size={16} className="text-gray-500" />
+                          )}
+                      </span>
+                    </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'
+                      >
+                        &times;
+                      </button>
+                      <DateRangePicker
+                        onChange={(item) => setState([item.selection])}
+                        showSelectionPreview={false}
+                        maxDate={new Date()}
+                        moveRangeOnFirstSelection={false}
+                        months={1}
+                        ranges={state}
+                        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>
+                      <div className='flex flex-row justify-end gap-3 mt-2'>
+                        <button
+                          className='px-4 py-1 bg-red-500 text-white rounded'
+                          onClick={handleReset}
+                        >
+                          Reset
+                        </button>
+                      </div>
+                    </div>
+                    )}
+                  </div>
                 </div>
               </div>
             </div>
@@ -1140,7 +1190,7 @@ const Transactions = ({ context = '' }) => {
                                     {saleOrder.products?.length > 1 && (
                                       <div className='flex flex-row gap-1 justify-start items-center'>
                                         {saleOrder.products
-                                          .slice(1, 6)
+                                          .slice(1, 4)
                                           .map((product, index) => (
                                             <Image
                                               key={index} // Tambahkan key untuk setiap elemen dalam map()
@@ -1149,16 +1199,21 @@ const Transactions = ({ context = '' }) => {
                                               className='object-contain object-center border border-gray_r-6 h-16 w-16 rounded-md'
                                             />
                                           ))}
-                                        <Link
-                                          href={`${router.pathname}/${saleOrder?.id}`}
-                                          className='text-sm text-red-500 text-nowrap'
-                                        >
-                                          {saleOrder.products?.length > 6
-                                            ? 'Lihat ' +
-                                              (saleOrder.products?.length - 6) +
-                                              ' produk lainnya'
-                                            : 'Lihat semua produk'}
-                                        </Link>
+                                        {saleOrder.products.length > 4 ? (
+                                          <Link
+                                            href={`${router.pathname}/${saleOrder?.id}`}
+                                            className='text-red-500 text-nowrap'
+                                          >
+                                            +{saleOrder.products.length - 4} lihat semua produk
+                                          </Link>
+                                        ) : (
+                                          <Link
+                                            href={`${router.pathname}/${saleOrder?.id}`}
+                                            className='text-red-500 text-nowrap'
+                                          >
+                                            Lihat semua produk
+                                          </Link>
+                                        )}
                                       </div>
                                     )}
                                   </div>
-- 
cgit v1.2.3

