diff --git a/src/_digifi/layout/components/paginatedListing/RecentBVNList.tsx b/src/_digifi/layout/components/paginatedListing/RecentBVNList.tsx new file mode 100644 index 0000000..2c49f2c --- /dev/null +++ b/src/_digifi/layout/components/paginatedListing/RecentBVNList.tsx @@ -0,0 +1,137 @@ +import { ReactNode, useEffect, useState } from "react"; +import { RecentBVNProps } from "../../../../app/pages/dashboard/model"; + +type PaginatedListProps = { + data: RecentBVNProps, + itemsPerPage?: number, + filterItem?: string[], + tableTitle?: string, + titleClass?:string, + children: (data:RecentBVNProps) => ReactNode; +} + +export default function RecentBVNList({ + data, + itemsPerPage = 5, + filterItem, + tableTitle, + titleClass, + children, +}:PaginatedListProps) { + 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 } }:{target: {value:string}}, name:string) => { + setSearchTerm(value); + let newFilteredData:any = data.filter((item:any) => + item[name].toLowerCase().startsWith(value.toLowerCase()) + ); + setFilteredData(newFilteredData); + setCurrentPage(0); + }; + + useEffect(() => { + setNewData( + filteredData?.slice(currentPage, numberOfSelection + currentPage) + ); + }, [currentPage, filteredData]); + + useEffect(()=>{ + setCurrentPage(0) + },[itemsPerPage]) + + return ( +
+

{tableTitle}

+ + {data.length > 0 && filterItem && ( +
+ {filterItem.map((item, index) => ( + + ))} +
+ )} + + {children(newData)} + + {/* show prev and next button if data exist */} + {(data.length > 0 && data.length > itemsPerPage) && ( +
+ + + {data.length && data.map((item, index)=>{ + item = item + if(index%itemsPerPage == 0 && index >= currentPage && index <= currentPage+itemsPerPage){ + return ( + + ) + } + })} + + +
+ )} +
+ ); +} diff --git a/src/_digifi/layout/components/paginatedListing/RecentLoanAppList.tsx b/src/_digifi/layout/components/paginatedListing/RecentLoanAppList.tsx new file mode 100644 index 0000000..271dbea --- /dev/null +++ b/src/_digifi/layout/components/paginatedListing/RecentLoanAppList.tsx @@ -0,0 +1,137 @@ +import { ReactNode, useEffect, useState } from "react"; +import { RecentApplicationsProps } from "../../../../app/pages/dashboard/model"; + +type PaginatedListProps = { + data: RecentApplicationsProps, + itemsPerPage?: number, + filterItem?: string[], + tableTitle?: string, + titleClass?:string, + children: (data:RecentApplicationsProps) => ReactNode; +} + +export default function RecentLoanAppList({ + data, + itemsPerPage = 5, + filterItem, + tableTitle, + titleClass, + children, +}:PaginatedListProps) { + 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 } }:{target: {value:string}}, name:string) => { + setSearchTerm(value); + let newFilteredData:any = data.filter((item:any) => + item[name].toLowerCase().startsWith(value.toLowerCase()) + ); + setFilteredData(newFilteredData); + setCurrentPage(0); + }; + + useEffect(() => { + setNewData( + filteredData?.slice(currentPage, numberOfSelection + currentPage) + ); + }, [currentPage, filteredData]); + + useEffect(()=>{ + setCurrentPage(0) + },[itemsPerPage]) + + return ( +
+

{tableTitle}

+ + {data.length > 0 && filterItem && ( +
+ {filterItem.map((item, index) => ( + + ))} +
+ )} + + {children(newData)} + + {/* show prev and next button if data exist */} + {(data.length > 0 && data.length > itemsPerPage) && ( +
+ + + {data.length && data.map((item, index)=>{ + item = item + if(index%itemsPerPage == 0 && index >= currentPage && index <= currentPage+itemsPerPage){ + return ( + + ) + } + })} + + +
+ )} +
+ ); +} diff --git a/src/_digifi/partials/widgets/lists/ListsWidget3.tsx b/src/_digifi/partials/widgets/lists/ListsWidget3.tsx index 92035b0..8f1e0ea 100644 --- a/src/_digifi/partials/widgets/lists/ListsWidget3.tsx +++ b/src/_digifi/partials/widgets/lists/ListsWidget3.tsx @@ -1,13 +1,17 @@ import React from 'react' -import {KTIcon} from '../../../helpers' -import {Dropdown1} from '../../content/dropdown/Dropdown1' +import { NewDateTimeFormatter } from '../../../lib/NewDateTimeFormatter' +// import {KTIcon} from '../../../helpers' +// import {Dropdown1} from '../../content/dropdown/Dropdown1' +import { DashDataProps, RecentBVNProps } from '../../../../app/pages/dashboard/model' +import RecentBVNList from '../../../layout/components/paginatedListing/RecentBVNList' type Props = { className: string + dashData?: DashDataProps } -const ListsWidget3: React.FC = ({className}) => { +const ListsWidget3: React.FC = ({dashData, className}) => { return (
{/* begin::Header */} @@ -31,132 +35,43 @@ const ListsWidget3: React.FC = ({className}) => { {/* end::Header */} {/* begin::Body */}
- {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - Create FireStone Logo - - Due in 2 Days -
- {/* end::Description */} - New -
- {/* end:Item */} - {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - Stakeholder Meeting - - Due in 3 Days -
- {/* end::Description */} - New -
- {/* end:Item */} - {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - Scoping & Estimations - - Due in 5 Days -
- {/* end::Description */} - New -
- {/* end:Item */} - {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - KPI App Showcase - - Due in 2 Days -
- {/* end::Description */} - New -
- {/* end:Item */} - {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - Project Meeting - - Due in 12 Days -
- {/* end::Description */} - New -
- {/* end:Item */} - {/* begin::Item */} -
- {/* begin::Bullet */} - - {/* end::Bullet */} - {/* begin::Checkbox */} -
- -
- {/* end::Checkbox */} - {/* begin::Description */} -
- - Customers Update - - Due in 1 week -
- {/* end::Description */} - New -
- {/* end:Item */} + {dashData?.loading ? + null + : + dashData?.data?.recent_bvn && dashData?.data?.recent_bvn.length ? + + {(data:RecentBVNProps) => ( + <> + {data?.map(item => ( +
+ {/* begin::Bullet */} + + {/* end::Bullet */} + {/* begin::Checkbox */} +
+ +
+ {/* end::Checkbox */} + {/* begin::Description */} +
+ + {item?.bvn} + + {NewDateTimeFormatter(item?.added)} +
+ {/* end::Description */} + New +
+ ))} + + )} +
+ : +

No list Found!

+ }
{/* end::Body */}
diff --git a/src/_digifi/partials/widgets/tables/TablesWidget10.tsx b/src/_digifi/partials/widgets/tables/TablesWidget10.tsx index df9d329..03188af 100644 --- a/src/_digifi/partials/widgets/tables/TablesWidget10.tsx +++ b/src/_digifi/partials/widgets/tables/TablesWidget10.tsx @@ -1,12 +1,17 @@ import { FC } from 'react' import {KTIcon, toAbsoluteUrl} from '../../../helpers' +import { DashDataProps, RecentApplicationsProps } from '../../../../app/pages/dashboard/model' +import { NewDateTimeFormatter } from '../../../lib/NewDateTimeFormatter' +import RecentLoanAppList from '../../../layout/components/paginatedListing/RecentLoanAppList' + type Props = { className: string + dashData?: DashDataProps } -const TablesWidget10: FC = ({className}) => { +const TablesWidget10: FC = ({className, dashData}) => { return (
{/* begin::Header */} @@ -32,371 +37,134 @@ const TablesWidget10: FC = ({className}) => {
*/} {/* end::Header */} + {/* begin::Body */} -
- {/* begin::Table container */} -
- {/* begin::Table */} - - {/* begin::Table head */} - - - - - - - - - - {/* end::Table head */} - {/* begin::Table body */} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {/* end::Table body */} -
-
- -
-
AuthorsCompanyProgressActions
-
- -
-
-
-
- -
-
- - Ana Simmons - - - HTML, JS, ReactJS - -
-
-
- - Intertico - - - Web, UI/UX Design - - -
-
- 50% -
-
-
-
-
-
- -
-
- -
-
-
-
- -
-
- - Jessie Clarcson - - - C#, ASP.NET, MS SQL - -
-
-
- - Agoda - - - Houses & Hotels - - -
-
- 70% -
-
-
-
-
-
- -
-
- -
-
-
-
- -
-
- - Lebron Wayde - - - PHP, Laravel, VueJS - -
-
-
- - RoadGee - - - Transportation - - -
-
- 60% -
-
-
-
-
-
- -
-
- -
-
-
-
- -
-
- - Natali Goodwin - - - Python, PostgreSQL, ReactJS - -
-
-
- - The Hill - - Insurance - -
-
- 50% -
-
-
-
-
-
- -
-
- -
-
-
-
- -
-
- - Kevin Leonard - - - HTML, JS, ReactJS - -
-
-
- - RoadGee - - - Art Director - - -
-
- 90% -
-
-
-
-
-
- -
- {/* end::Table */} -
- {/* end::Table container */} -
+ {dashData?.loading ? + null + : dashData?.data?.recent_applications ? + + {(data:RecentApplicationsProps)=>( + <> +
+ {/* begin::Table container */} +
+ {/* begin::Table */} + + {/* begin::Table head */} + + + + + + + + + + {/* end::Table head */} + {/* begin::Table body */} + + {data && data.length ? + data.map(item => ( + + + + + + + + )) + : + + + + } + + {/* end::Table body */} +
+
+ +
+
AuthorsAmountProgressActions
+
+ +
+
+
+
+ +
+
+ + {item?.firstname} {item?.lastname} + + + {NewDateTimeFormatter(item?.added)} + +
+
+
+ + {item.loan_amount} + + + {item?.sales_agent? `Agent: ${item?.sales_agent}` : ``} + + +
+
+ 50% +
+
+
+
+
+
+ +
No data found!
+ {/* end::Table */} +
+ {/* end::Table container */} +
+ + )} +
+ : + null + } {/* begin::Body */} + ) } diff --git a/src/app/modules/auth/core/AxiosCallHelper.ts b/src/app/modules/auth/core/AxiosCallHelper.ts index b25e2cf..2413696 100644 --- a/src/app/modules/auth/core/AxiosCallHelper.ts +++ b/src/app/modules/auth/core/AxiosCallHelper.ts @@ -45,6 +45,29 @@ export function postAuxEnd(uri:string, reqData:any):Promise { ); } }); +} + + +export function getAuxEnd(uri: string, reqData?: any): Promise { + const endPoint = import.meta.env.VITE_APP_USER_ENDPOINT + uri; + const formData = new FormData(); + for (let value in reqData) { + formData.append(value, reqData[value]); } + return axios + .get(endPoint, reqData) + .then((response: {}) => { + // if (response.data.internal_return == "-9999") { + // localStorage.clear(); + // window.location.href = `/login?sessionExpired=true`; + // } + return response; + }) + .catch((error: any) => { + console.log( + "ERROR3-------------------------------------------------------", error + ); + }); +} diff --git a/src/app/modules/auth/core/_requests.ts b/src/app/modules/auth/core/_requests.ts index 724b653..88eeb94 100644 --- a/src/app/modules/auth/core/_requests.ts +++ b/src/app/modules/auth/core/_requests.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { AuthModel, UserModel } from "./_models"; -import { postAuxEnd } from "./AxiosCallHelper"; +import { postAuxEnd, getAuxEnd } from "./AxiosCallHelper"; const API_URL = import.meta.env.VITE_APP_API_URL; @@ -10,6 +10,7 @@ const API_URL = import.meta.env.VITE_APP_API_URL; export const GET_USER_BY_ACCESSTOKEN_URL = '/identity/verify_token' export const LOGIN_URL = '/identity/token' +export const USER_DASH_DETAILS = `/dash`; export const REGISTER_URL = `${API_URL}/register`; export const REQUEST_PASSWORD_URL = `${API_URL}/forgot_password`; @@ -55,3 +56,7 @@ export function requestPassword(email: string) { export function getUserByToken(token: string) { return postAuxEnd(GET_USER_BY_ACCESSTOKEN_URL, {token}) } + +export function getUserDashDetails() { + return getAuxEnd(USER_DASH_DETAILS) +} diff --git a/src/app/pages/dashboard/DashboardWrapper.tsx b/src/app/pages/dashboard/DashboardWrapper.tsx index 5b51b99..e888ab1 100644 --- a/src/app/pages/dashboard/DashboardWrapper.tsx +++ b/src/app/pages/dashboard/DashboardWrapper.tsx @@ -1,15 +1,15 @@ -import { FC } from 'react'; +import { FC, useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import { toAbsoluteUrl } from '../../../_digifi/helpers'; import { PageTitle } from '../../../_digifi/layout/core'; import { - ListsWidget2, + // ListsWidget2, ListsWidget3, - ListsWidget4, - ListsWidget6, - TablesWidget5, + // ListsWidget4, + // ListsWidget6, + // TablesWidget5, TablesWidget10, - MixedWidget8, + // MixedWidget8, CardsWidget7, CardsWidget17, CardsWidget20, @@ -18,76 +18,93 @@ import { } from '../../../_digifi/partials/widgets'; import { ToolbarWrapper } from '../../../_digifi/layout/components/toolbar'; import { Content } from '../../../_digifi/layout/components/content'; +import { getUserDashDetails } from '../../modules/auth/core/_requests'; +import { DashDataProps } from './model'; -const DashboardPage: FC = () => ( - <> - - - {/* begin::Row */} -
- {/* begin::Col */} -
- - -
- {/* end::Col */} +const DashboardPage: FC = () => { + const [dashDetails, setDashDetails] = useState({loading:true, data:{}}) - {/* begin::Col */} -
- - -
- {/* end::Col */} + useEffect(()=>{ + getUserDashDetails().then(res => { + setDashDetails({loading:false, data:res.data}) + }).catch(err => { + setDashDetails({loading:false, data:{}}) + console.log(err) + }) + },[]) - {/* begin::Col */} -
- -
- {/* end::Col */} -
- {/* end::Row */} + return ( + <> + + + {/* begin::Row */} +
+ {/* begin::Col */} +
+ + +
+ {/* end::Col */} - {/* begin::Row */} -
- {/* begin::Col */} -
- {/* */} -
- {/* end::Col */} + {/* begin::Col */} +
+ + +
+ {/* end::Col */} - {/* begin::Col */} -
- {/* */} + {/* begin::Col */} +
+ +
+ {/* end::Col */}
- {/* end::Col */} -
- {/* end::Row */} + {/* end::Row */} - {/* begin::Row */} -
-
- + {/* begin::Row */} +
+ {/* begin::Col */} +
+ {/* */} +
+ {/* end::Col */} + + {/* begin::Col */} +
+ {/* */} +
+ {/* end::Col */}
-
- + {/* end::Row */} + + {/* begin::Row */} +
+ {/* BVN VERIFICATION */} +
+ +
+ {/* RECENT LOAN APPLICATION */} +
+ +
-
- {/* end::Row */} - - -); + {/* end::Row */} + + + ) +} const DashboardWrapper: FC = () => { const intl = useIntl(); diff --git a/src/app/pages/dashboard/model.ts b/src/app/pages/dashboard/model.ts new file mode 100644 index 0000000..fa2dcf8 --- /dev/null +++ b/src/app/pages/dashboard/model.ts @@ -0,0 +1,43 @@ +export type RecentApplicationsProps = { + firstname?: string + lastname?: string + uid?: string + loan_amount?: string + payment_month?: string + sales_agent?: string + gender?: string | null + marital_status?: string + email?: string + address?: string + state?: string + country?: string + status?: string + added?: string + updated?: string +}[] + +export type RecentBVNProps = { + id?: string + uid?: string + bvn?: string + status?: string + added?: string + updated?: string + firstname?: string | null + lastname?: string | null + middlename?: string | null + gender?: string | null + birthdate?: string | null + phone?: string | null + nationality?: string | null +}[] + + +export type DashDataProps = { + loading: boolean, + data: { + call_return?: string + recent_applications? : RecentApplicationsProps + recent_bvn?: RecentBVNProps + } + } \ No newline at end of file