Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c2bda67ab1 | |||
| cea0ebfe82 |
@@ -6,7 +6,7 @@ TWITTER_URL=https://twitter.com
|
|||||||
INSTAGRAM_URL=https://www.instagram.com
|
INSTAGRAM_URL=https://www.instagram.com
|
||||||
|
|
||||||
# BACKEND END POINTS
|
# BACKEND END POINTS
|
||||||
REACT_APP_MAIN_API='https://backoffice-apidev.simbrellang.net'
|
REACT_APP_MAIN_API='http://backoffice-apidev.simbrellang.net:14700'
|
||||||
|
|
||||||
# ENQUIRIES CONTACTS
|
# ENQUIRIES CONTACTS
|
||||||
VITE_CALL_ENDPOINT='09099000000'
|
VITE_CALL_ENDPOINT='09099000000'
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ VITE_TWITTER_URL=https://twitter.com
|
|||||||
VITE_INSTAGRAM_URL=https://www.instagram.com
|
VITE_INSTAGRAM_URL=https://www.instagram.com
|
||||||
|
|
||||||
# BACKEND END POINTS
|
# BACKEND END POINTS
|
||||||
REACT_APP_MAIN_API='https://backoffice-apidev.simbrellang.net'
|
REACT_APP_MAIN_API='http://backoffice-apidev.simbrellang.net:14700'
|
||||||
|
|
||||||
# ENQUIRIES CONTACTS
|
# ENQUIRIES CONTACTS
|
||||||
VITE_CALL_ENDPOINT='09099000000'
|
VITE_CALL_ENDPOINT='09099000000'
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ TWITTER_URL=https://twitter.com
|
|||||||
INSTAGRAM_URL=https://www.instagram.com
|
INSTAGRAM_URL=https://www.instagram.com
|
||||||
|
|
||||||
# BACKEND END POINTS
|
# BACKEND END POINTS
|
||||||
REACT_APP_MAIN_API='https://backoffice-apidev.simbrellang.net'
|
REACT_APP_MAIN_API='http://backoffice-apidev.simbrellang.net:14700'
|
||||||
|
|
||||||
# ENQUIRIES CONTACTS
|
# ENQUIRIES CONTACTS
|
||||||
VITE_CALL_ENDPOINT='09099000000'
|
VITE_CALL_ENDPOINT='09099000000'
|
||||||
|
|||||||
@@ -1,39 +1,43 @@
|
|||||||
import React from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { keepPreviousData, useQuery } from "@tanstack/react-query";
|
||||||
import {Link} from 'react-router-dom'
|
import {Link} from 'react-router-dom'
|
||||||
|
|
||||||
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
|
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
|
||||||
import TableWrapper from '../tableWrapper/TableWrapper'
|
import TablePaginatedWrapper from '../tableWrapper/TablePaginatedWrapper'
|
||||||
import Icons from '../Icons'
|
import Icons from '../Icons'
|
||||||
|
|
||||||
import Avatar from '../../assets/user_avatar.jpg'
|
import Avatar from '../../assets/user_avatar.jpg'
|
||||||
import queryKeys from '../../services/queryKeys'
|
import queryKeys from '../../services/queryKeys'
|
||||||
import { selectLoan } from '../../services/siteServices'
|
import { getTransactions } from '../../services/siteServices'
|
||||||
import getDateFromDateString from '../../helpers/GetDateFromDateString';
|
import getDateFromDateString from '../../helpers/GetDateFromDateString';
|
||||||
import getTimeFromDateString from '../../helpers/GetTimeFromDateString';
|
import getTimeFromDateString from '../../helpers/GetTimeFromDateString';
|
||||||
|
|
||||||
export default function RequestCom() {
|
export default function RequestCom() {
|
||||||
|
|
||||||
const {data, isFetching, isError, error} = useQuery({
|
const [page, setPage] = useState(1)
|
||||||
queryKey: queryKeys.select_loan,
|
|
||||||
queryFn: () => selectLoan()
|
const {data, isFetching, isError, error, isPlaceholderData, isPending} = useQuery({
|
||||||
|
queryKey: [...queryKeys.transactions, page],
|
||||||
|
queryFn: () => getTransactions({page}),
|
||||||
|
// placeholderData: keepPreviousData,
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectUsers = data?.data?.result_data?.data // APPLY LOAN LIST
|
const selectUsers = data?.data?.transactions // TRANSACTIONS LIST
|
||||||
|
const pagination = data?.data?.pagination
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='w-full flex flex-col gap-8'>
|
<div className='w-full flex flex-col gap-8'>
|
||||||
<BreadcrumbCom title='Request' paths={['Dashboard', 'Request']} />
|
<BreadcrumbCom title='Request' paths={['Dashboard', 'Request']} />
|
||||||
|
|
||||||
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
|
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
|
||||||
{isFetching ?
|
{isPending ?
|
||||||
<>
|
<>
|
||||||
<p className='text-slate-800'>Loading...</p>
|
<p className='text-slate-800'>Loading...</p>
|
||||||
</>
|
</>
|
||||||
: isError ?
|
: isError ?
|
||||||
<p className='text-red-500'>{error.message}</p>
|
<p className='text-red-500'>{error.message}</p>
|
||||||
:
|
:
|
||||||
<TableWrapper data={selectUsers} itemsPerPage={15}>
|
<TablePaginatedWrapper data={selectUsers} isFetching={isFetching} setPage={setPage} itemsPerPage={pagination?.limit} pagination={pagination}>
|
||||||
{({ data }) => (
|
{({ data }) => (
|
||||||
<>
|
<>
|
||||||
<table className="py-2 w-full text-sm">
|
<table className="py-2 w-full text-sm">
|
||||||
@@ -42,9 +46,9 @@ export default function RequestCom() {
|
|||||||
<th scope="col" className="px-2 py-2">
|
<th scope="col" className="px-2 py-2">
|
||||||
Name
|
Name
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" className="px-2">
|
{/* <th scope="col" className="px-2">
|
||||||
Loan
|
Loan
|
||||||
</th>
|
</th> */}
|
||||||
<th scope="col" className="px-2">
|
<th scope="col" className="px-2">
|
||||||
Added
|
Added
|
||||||
</th>
|
</th>
|
||||||
@@ -55,25 +59,25 @@ export default function RequestCom() {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{(data && data.length > 0) ? data?.map((item, index) => (
|
{(data && data.length > 0) ? data?.map((item, index) => (
|
||||||
<tr className="py-2 border-t border-dashed border-slate-300">
|
<tr key={index} className="py-2 border-t border-dashed border-slate-300">
|
||||||
<td className="px-2 py-2">
|
<td className="px-2 py-2">
|
||||||
<div className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
|
<div className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
|
||||||
<img className="w-10 h-10 rounded-md" src={Avatar} alt="Jese image" />
|
<img className="w-10 h-10 rounded-md" src={Avatar} alt="Jese image" />
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="text-base font-semibold">{item?.name || ''}</div>
|
<div className="text-base font-semibold">{item?.account_id || ''}</div>
|
||||||
<div className="font-normal text-gray-500">{item?.bvn}</div>
|
<div className="font-normal text-gray-500">{item?.transaction_id}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2">
|
{/* <td className="px-2">
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="text-base font-semibold">{item?.loan}</div>
|
<div className="text-base font-semibold">{item?.loan}</div>
|
||||||
<div className="font-normal text-gray-500">{item?.description}</div>
|
<div className="font-normal text-gray-500">{item?.description}</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td> */}
|
||||||
<td className="px-2">
|
<td className="px-2">
|
||||||
<div className="text-left">
|
<div className="text-left">
|
||||||
<div className="font-normal text-gray-500">{getDateFromDateString(item?.added)} {getTimeFromDateString(item?.added)}</div>
|
<div className="font-normal text-gray-500">{getDateFromDateString(item?.created_at)}</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-2 text-right">
|
<td className="px-2 text-right">
|
||||||
@@ -93,7 +97,7 @@ export default function RequestCom() {
|
|||||||
))
|
))
|
||||||
:
|
:
|
||||||
<tr className="py-2 border-t border-dashed border-slate-300">
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
<td className="px-3 py-2" colSpan={4}>
|
<td className="px-3 py-2" colSpan={3}>
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex justify-center items-center">
|
||||||
No Record Found
|
No Record Found
|
||||||
</div>
|
</div>
|
||||||
@@ -104,7 +108,7 @@ export default function RequestCom() {
|
|||||||
</table>
|
</table>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</TableWrapper>
|
</TablePaginatedWrapper>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import MainBtn from "../MainBtn";
|
||||||
|
import Icons from "../Icons";
|
||||||
|
|
||||||
|
|
||||||
|
export default function TablePaginatedWrapper({
|
||||||
|
data = [],
|
||||||
|
itemsPerPage = 5,
|
||||||
|
pagination,
|
||||||
|
setPage,
|
||||||
|
isFetching,
|
||||||
|
filterItem,
|
||||||
|
children,
|
||||||
|
}) {
|
||||||
|
const [isLoading, setIsLoading] = useState(isFetching)
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
const [filteredData, setFilteredData] = useState(data);
|
||||||
|
|
||||||
|
const [currentPage, setCurrentPage] = useState(0);
|
||||||
|
const [newData, setNewData] = useState([]);
|
||||||
|
|
||||||
|
const numberOfSelection = itemsPerPage;
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setPage(prev => prev - 1)
|
||||||
|
};
|
||||||
|
const handleNext = () => {
|
||||||
|
setPage(prev => prev + 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearch = ({ target: { value } }, name) => {
|
||||||
|
setSearchTerm(value);
|
||||||
|
let newFilteredData = data.filter((item) =>
|
||||||
|
item[name].toLowerCase().startsWith(value.toLowerCase())
|
||||||
|
);
|
||||||
|
setFilteredData(newFilteredData);
|
||||||
|
setCurrentPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsLoading(true)
|
||||||
|
setTimeout(()=>{
|
||||||
|
setNewData(
|
||||||
|
filteredData?.slice(currentPage, numberOfSelection + currentPage)
|
||||||
|
);
|
||||||
|
setIsLoading(false)
|
||||||
|
},1000)
|
||||||
|
}, [currentPage, filteredData, numberOfSelection]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setCurrentPage(0)
|
||||||
|
},[itemsPerPage])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-full">
|
||||||
|
{data.length > 0 && filterItem && (
|
||||||
|
<div className="mb-10 flex justify-end items-center gap-2">
|
||||||
|
{filterItem.map((item, index) => (
|
||||||
|
<label
|
||||||
|
key={index}
|
||||||
|
className="flex flex-col sm:flex-row items-center gap-2 text-slate-600 dark:text-slate-100 transition-all duration-500"
|
||||||
|
>
|
||||||
|
Search by {item[0].toUpperCase() + item.slice(1)}
|
||||||
|
<input
|
||||||
|
name={item}
|
||||||
|
type="text"
|
||||||
|
className="py-1 px-2 text-sm min-w-[100px] text-black dark:text-white bg-white dark:bg-slate-800 rounded-full border-0 outline-none ring-1 ring-slate-300 dark:ring-white transition-all duration-500"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => {
|
||||||
|
handleSearch(e, item);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="w-full overflow-x-auto">
|
||||||
|
{children({ data: newData })}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='w-full flex flex-col lg:flex-row justify-center items-center gap-3 md:gap-6'>
|
||||||
|
<div className="text-sm text-center lg:text-left font-normal text-gray-500 dark:text-gray-400 block w-full">Showing <span className="font-semibold text-gray-900 dark:text-white">
|
||||||
|
{isLoading ? '----' : `page ${pagination?.current_page}`}</span> of <span className="font-semibold text-gray-900 dark:text-white">{pagination?.total_pages}</span>
|
||||||
|
</div>
|
||||||
|
{(newData.length >= 0) &&
|
||||||
|
<div className='flex items-center gap-3 md:gap-6'>
|
||||||
|
<MainBtn
|
||||||
|
onClick={handlePrev}
|
||||||
|
// text='Prev'
|
||||||
|
className={`${!pagination?.has_prev ? 'bg-primary/50 pointer-events-none' : 'bg-primary'} text-white-light text-center flex justify-center gap-2 items-center`}
|
||||||
|
disabled={isLoading || !pagination?.has_prev}
|
||||||
|
>
|
||||||
|
<Icons name='prev' />
|
||||||
|
</MainBtn>
|
||||||
|
<MainBtn
|
||||||
|
onClick={handleNext}
|
||||||
|
// text='Next'
|
||||||
|
className={`${!pagination?.has_next ? 'bg-primary/50 pointer-events-none' : 'bg-primary'} text-white-light text-center flex justify-center gap-2 items-center`}
|
||||||
|
disabled={isLoading || !pagination?.has_next}
|
||||||
|
>
|
||||||
|
<Icons name='next' />
|
||||||
|
</MainBtn>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading && <TableIsLoading />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TableIsLoading = () => {
|
||||||
|
return (
|
||||||
|
<div className="w-full absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-[991] inset-0 flex justify-center items-center">
|
||||||
|
<p className="rounded-md shadow-md p-4 bg-white/90 dark:bg-gray-900 text-brown dark:text-white">Loading...</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
const queryKeys = {
|
const queryKeys = {
|
||||||
dashboard: ['dashboard'],
|
dashboard: ['dashboard'],
|
||||||
loans: ['loans'],
|
loans: ['loans'],
|
||||||
|
transactions: ['transactions'],
|
||||||
apply_loan: ['apply'],
|
apply_loan: ['apply'],
|
||||||
select_loan: ['select-loan'],
|
select_loan: ['select-loan'],
|
||||||
approved_loan: ['approved-loan'],
|
approved_loan: ['approved-loan'],
|
||||||
|
|||||||
@@ -56,12 +56,18 @@ export const getDashData = (reqData) => {
|
|||||||
return getAuxEnd(`/dashboard`, postData)
|
return getAuxEnd(`/dashboard`, postData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET APPLIED LOANS TABLE
|
// FUNCTION TO GET LOANS TABLE
|
||||||
export const getLoans = (reqData) => {
|
export const getLoans = (reqData) => {
|
||||||
const postData = { ...reqData }
|
const postData = { ...reqData }
|
||||||
return getAuxEnd(`/loans`, postData)
|
return getAuxEnd(`/loans`, postData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET TRANSACTIONS TABLE
|
||||||
|
export const getTransactions = (reqData) => {
|
||||||
|
const postData = { ...reqData }
|
||||||
|
return getAuxEnd(`/transactions`, postData)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user