diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-03-12 09:38:31 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-03-12 09:38:31 +0700 |
| commit | 0fada18346571b321ceb46689659b544ffc9dfe2 (patch) | |
| tree | 662780254dd6b22ab2629e745134de5c95172537 | |
| parent | e38dff05fd629ef054d571e7d3b066f1bdd5520b (diff) | |
<iman> fix transaction
| -rw-r--r-- | package.json | 4 | ||||
| -rw-r--r-- | src/lib/transaction/components/Transactions.jsx | 227 | ||||
| -rw-r--r-- | src/styles/globals.css | 4 |
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; } |
