From 8fb9e42ec4ce706c78492d52c41dbf1f268586e3 Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Tue, 18 Feb 2025 19:13:08 +0100 Subject: [PATCH] backend endpoint added to env file --- .env | 2 +- .env.development | 2 +- .env.production | 2 +- src/App.js | 14 +++ src/RouteLinks.js | 2 +- src/SiteRoutes.jsx | 4 +- .../layouts/aside/DashboardAside.jsx | 4 +- src/components/tableWrapper/TableWrapper.jsx | 118 ++++++++++++++++++ .../{Disbursements.jsx => ApplyPage.jsx} | 4 +- src/services/queryKeys.js | 5 + src/services/siteServices.js | 57 +++++++++ 11 files changed, 204 insertions(+), 10 deletions(-) create mode 100644 src/components/tableWrapper/TableWrapper.jsx rename src/pages/{Disbursements.jsx => ApplyPage.jsx} (62%) create mode 100644 src/services/queryKeys.js create mode 100644 src/services/siteServices.js diff --git a/.env b/.env index b6fbd9d..86810db 100644 --- a/.env +++ b/.env @@ -6,7 +6,7 @@ TWITTER_URL=https://twitter.com INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' +REACT_APP_MAIN_API='https://devcore.digifi.chiefsoft.net' # ENQUIRIES CONTACTS VITE_CALL_ENDPOINT='09099000000' diff --git a/.env.development b/.env.development index 7f02815..b7fc43e 100644 --- a/.env.development +++ b/.env.development @@ -6,7 +6,7 @@ VITE_TWITTER_URL=https://twitter.com VITE_INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' +REACT_APP_MAIN_API='https://devcore.digifi.chiefsoft.net' # ENQUIRIES CONTACTS VITE_CALL_ENDPOINT='09099000000' diff --git a/.env.production b/.env.production index b6fbd9d..86810db 100644 --- a/.env.production +++ b/.env.production @@ -6,7 +6,7 @@ TWITTER_URL=https://twitter.com INSTAGRAM_URL=https://www.instagram.com # BACKEND END POINTS -VITE_USERS_ENDPOINT='https://digifi-apidev.chiefsoft.net/digiusers/v1' +REACT_APP_MAIN_API='https://devcore.digifi.chiefsoft.net' # ENQUIRIES CONTACTS VITE_CALL_ENDPOINT='09099000000' diff --git a/src/App.js b/src/App.js index d3fcfda..fe9f8ef 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,6 @@ import { useEffect } from 'react' import { useLocation } from 'react-router-dom' +import { QueryClientProvider, QueryClient } from '@tanstack/react-query' import SiteRoutes from './SiteRoutes'; import LogoutModal from './components/layouts/LogoutModal'; @@ -17,12 +18,25 @@ function App() { window.scrollTo(0,0) },[pathname]) + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + retry: 3, + // refetchOnMount: false, + staleTime: Infinity // can also be a number in millisecond + }, + }, + }) + return ( <> + {/* LOGOUT MODAL */} {logoutModal && setLogoutModal(false)} />} + ); } diff --git a/src/RouteLinks.js b/src/RouteLinks.js index 902b2d9..2fda297 100644 --- a/src/RouteLinks.js +++ b/src/RouteLinks.js @@ -4,7 +4,7 @@ const RouteLinks = { homePage: '/', usersPage: '/users', approvedLoans: '/loans/approved', - disbursements: '/loans/disbursements', + apply: '/loans/apply', } export default RouteLinks \ No newline at end of file diff --git a/src/SiteRoutes.jsx b/src/SiteRoutes.jsx index 17faeed..a4cc89f 100644 --- a/src/SiteRoutes.jsx +++ b/src/SiteRoutes.jsx @@ -9,7 +9,7 @@ import LoginPage from './pages/LoginPage' // LOGIN PAGE import HomePage from './pages/HomePage' // Home PAGE import UsersPage from './pages/UsersPage' // Users PAGE import ApprovedLoansPage from './pages/ApprovedLoansPage' // APPROVED LOANS PAGE -import Disbursements from './pages/Disbursements' // DISBURSEMENTS LOANS PAGE +import ApplyPage from './pages/ApplyPage' // APPLY LOANS PAGE // const Home = lazy(() => import('./pages/Home')); @@ -23,7 +23,7 @@ export default function SiteRoutes() { } /> {`*/HOME PAGE*/`} } /> {`*/USERS PAGE*/`} } /> {`*/APPROVED LOANS PAGE*/`} - } /> {`*/DISBURSEMENTS LOANS PAGE*/`} + } /> {`*/APPLY LOANS PAGE*/`} {/* ERROR PAGE */} diff --git a/src/components/layouts/aside/DashboardAside.jsx b/src/components/layouts/aside/DashboardAside.jsx index 4f3c40a..bb397de 100644 --- a/src/components/layouts/aside/DashboardAside.jsx +++ b/src/components/layouts/aside/DashboardAside.jsx @@ -93,9 +93,9 @@ export default function DashboardAside({shrinkAside=false}) { const asideNavLinks = [ {name:'Dashboard', status:1, icon: 'dashboard', to: RouteLinks.homePage}, {name:'Salary Loan', title:'Loan', status:1, icon: 'money', subLinks: [ - {name: 'Applications', status:1, icon: 'dot', to: '#'}, + {name: 'Select', status:1, icon: 'dot', to: '#'}, + {name: 'Apply', status:1, icon: 'dot', to: RouteLinks.apply}, {name: 'Approved', status:1, icon: 'dot', to: RouteLinks.approvedLoans}, - {name: 'Disbursements', status:1, icon: 'dot', to: RouteLinks.disbursements}, {name: 'Payments', status:1, icon: 'dot', to: '#'}, {name: 'Configuration', status:1, icon: 'dot', to: '#'}, ], diff --git a/src/components/tableWrapper/TableWrapper.jsx b/src/components/tableWrapper/TableWrapper.jsx new file mode 100644 index 0000000..f84b2ba --- /dev/null +++ b/src/components/tableWrapper/TableWrapper.jsx @@ -0,0 +1,118 @@ +import { ReactNode, useEffect, useState } from "react"; +import MainBtn from "../MainBtn"; + + +export default function TableWrapper({ + data = [], + itemsPerPage = 5, + filterItem, + children, +}) { + const [isLoading, setIsLoading] = useState(true) + const [searchTerm, setSearchTerm] = useState(""); + const [filteredData, setFilteredData] = useState(data); + + const [currentPage, setCurrentPage] = useState(0); + const [newData, setNewData] = useState([]); + + const numberOfSelection = itemsPerPage; + + const handlePrev = () => { + if (currentPage != 0) { + setCurrentPage((prev) => prev - numberOfSelection); + } + }; + const handleNext = () => { + if (currentPage < data.length) { + setCurrentPage((prev) => prev + numberOfSelection); + } + }; + + 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]); + + useEffect(()=>{ + setCurrentPage(0) + },[itemsPerPage]) + + return ( +
+ {data.length > 0 && filterItem && ( +
+ {filterItem.map((item, index) => ( + + ))} +
+ )} + +
+
+ {children({ data: newData })} +
+ + {/* PAGINATION BUTTON */} + {newData.length > 0 && +
+
Showing + {isLoading ? '----' : `${currentPage + 1}-${currentPage + numberOfSelection >= data.length ? data.length : (currentPage + numberOfSelection)}`} of {data.length} +
+
+ + = data.length ? 'bg-sky-600/50 pointer-events-none' : 'bg-sky-600'} text-white-light`} + disabled={isLoading} + /> +
+
+ } +
+ + {isLoading && } +
+ ); +} + +const TableIsLoading = () => { + return ( +
+

Loading...

+
+ ) +} diff --git a/src/pages/Disbursements.jsx b/src/pages/ApplyPage.jsx similarity index 62% rename from src/pages/Disbursements.jsx rename to src/pages/ApplyPage.jsx index 5ac5db2..db5b57e 100644 --- a/src/pages/Disbursements.jsx +++ b/src/pages/ApplyPage.jsx @@ -1,10 +1,10 @@ import React from 'react' import BreadcrumbCom from '../components/breadcrumb/BreadcrumbCom' -export default function Disbursements() { +export default function ApplyPage() { return (
- +

coming soon ...

diff --git a/src/services/queryKeys.js b/src/services/queryKeys.js new file mode 100644 index 0000000..1c6d36d --- /dev/null +++ b/src/services/queryKeys.js @@ -0,0 +1,5 @@ +const queryKeys = { + dummy: [''] +} + +export default queryKeys \ No newline at end of file diff --git a/src/services/siteServices.js b/src/services/siteServices.js new file mode 100644 index 0000000..6084d35 --- /dev/null +++ b/src/services/siteServices.js @@ -0,0 +1,57 @@ +import axios from "axios" + + +axios.interceptors.request.use( + config => { + config.headers = { + Accept: "application/json", + "Access-Control-Allow-Origin": "*", + // "Access-Control-Expose-Headers": "Access-Control-Allow-Origin", + // "Access-Control-Allow-Headers": "Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token", + "Content-Type": "application/json;charset=UTF-8", + // 'Authorization': `Bearer ${localStorage.getItem('token')}` + }; + // config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`; + // config.baseURL = process.env.REACT_APP_MAIN_API + return config; + }, + error => { + return Promise.reject(error); + } +); + +const postAuxEnd = (path, postData, media=false) => { + const basePath = media ? process.env.REACT_APP_MAIN_API : process.env.REACT_APP_MAIN_API + return axios.post(`${basePath}${path}`, postData).then(res => { + return res + }).catch(err => { + throw new Error(err.response.data.message); + }) +} + +const getAuxEnd = (path, reqData= null) => { + const basePath = process.env.REACT_APP_MAIN_API + return axios.get(`${basePath}${path}`,{ params: reqData }).then(res => { + return res + // localStorage.clear(); + // window.location.href = `/login?sessionExpired=true`; + }).catch(err => { + throw new Error(err); + // throw new Error(err.response.data.message); + // return err + }) +} + +// FUNCTION TO LOGIN USER IN +export const loginUser = (reqData) => { + let postData = { + ...reqData + } + return postAuxEnd('/salary/login', postData, false) +} + +// FUNCTION TO GET DEMO USERS +export const demoUsersList = (reqData) => { + const postData = { ...reqData } + return getAuxEnd(`/salary/demousers`, postData) +} \ No newline at end of file