summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2025-03-12 09:38:31 +0700
committerit-fixcomart <it@fixcomart.co.id>2025-03-12 09:38:31 +0700
commit0fada18346571b321ceb46689659b544ffc9dfe2 (patch)
tree662780254dd6b22ab2629e745134de5c95172537
parente38dff05fd629ef054d571e7d3b066f1bdd5520b (diff)
<iman> fix transaction
-rw-r--r--package.json4
-rw-r--r--src/lib/transaction/components/Transactions.jsx227
-rw-r--r--src/styles/globals.css4
3 files changed, 203 insertions, 32 deletions
diff --git a/package.json b/package.json
index 9e7fcc1b..92d9bc3a 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"classnames": "^2.3.2",
"clsx": "^2.0.0",
"cookies-next": "^2.1.1",
+ "date-fns": "^4.1.0",
"flowbite": "^1.6.4",
"framer-motion": "^7.10.3",
"lodash-contrib": "^4.1200.1",
@@ -38,7 +39,8 @@
"next-pwa": "^5.6.0",
"next-seo": "^5.15.0",
"nodemailer": "^6.8.0",
- "react": "18.2.0",
+ "react": "^18.2.0",
+ "react-date-range": "^2.0.1",
"react-dom": "18.2.0",
"react-google-recaptcha": "^2.1.0",
"react-hook-form": "^7.42.1",
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>
)}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 6447284e..d9b82447 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -46,8 +46,8 @@ button {
@apply text-[11px]
leading-none
font-medium
- px-1
- py-1
+ px-2
+ py-2
rounded
w-fit;
}