From a2e039eab415eab6a05e0520f53ecf4155d2cc89 Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Mon, 6 May 2024 14:44:42 +0100 Subject: [PATCH 1/2] initial commit --- .../Dashboard/DashboardHomeIntro.tsx | 55 +++++++- src/components/Icons/Icons.tsx | 4 +- src/components/paginated-list/PendingList.tsx | 133 ++++++++++++++++++ src/lib/NewDateTimeFormatter.ts | 18 +++ src/models/DataTypes.ts | 9 ++ 5 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 src/components/paginated-list/PendingList.tsx create mode 100644 src/lib/NewDateTimeFormatter.ts create mode 100644 src/models/DataTypes.ts diff --git a/src/components/Dashboard/DashboardHomeIntro.tsx b/src/components/Dashboard/DashboardHomeIntro.tsx index 9406594..4a656c7 100644 --- a/src/components/Dashboard/DashboardHomeIntro.tsx +++ b/src/components/Dashboard/DashboardHomeIntro.tsx @@ -1,7 +1,8 @@ import React, { FC } from "react"; import NairaBag from "../../assets/images/dashboard/naira-bag.png"; -import { Button } from "../"; +import { Button, Icons } from "../"; import { useSelector } from "react-redux"; +import PendingList from "../paginated-list/PendingList"; export interface DashBoardCardProps { title?: string; @@ -76,7 +77,7 @@ interface DashboardHomeIntroProps { const DashboardHomeIntro: FC = ({ handleNextStep, step }) => { const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable return ( - <> +
{step == 1 ? <>

Hello, {userDetails.firstname}

@@ -114,12 +115,60 @@ const DashboardHomeIntro: FC = ({ handleNextStep, step
} - +
+ + {({data}:any)=>( +
+ + + + + + + + + + + + {data.map((item:any, index:any) =>( + + + + + + + + ))} + +
DateAmountPayment TermStatusAction
{'item.date'}The Sliding Mr. Bones (Next Stop, Pottersville)12Malcolm Lockyer + +
+
+ )} +
+
+ ); }; export default DashboardHomeIntro; +const dummyData = [ + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'}, + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'}, + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'}, + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'}, + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'}, + {id: 1, name: 'obi John', last_login: '12/12/2024', image: 'string'} +] + // {/*
// ) :name == 'arrow-down'? + :name == 'arrow-right'? + :name == "dash-icon" ? ( dash-icon ) : null} diff --git a/src/components/paginated-list/PendingList.tsx b/src/components/paginated-list/PendingList.tsx new file mode 100644 index 0000000..d054e2f --- /dev/null +++ b/src/components/paginated-list/PendingList.tsx @@ -0,0 +1,133 @@ +import { ReactNode, useEffect, useState } from "react"; + +type PaginatedListProps = { + data: { id: number, name: string, last_login: string, image: string }[], + itemsPerPage?: number, + filterItem?: string[], + tableTitle?: string, + titleClass?:string, + children: (data:any) => ReactNode; +} + +export default function PendingList({ + 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({ data: 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/lib/NewDateTimeFormatter.ts b/src/lib/NewDateTimeFormatter.ts new file mode 100644 index 0000000..18da0e7 --- /dev/null +++ b/src/lib/NewDateTimeFormatter.ts @@ -0,0 +1,18 @@ + +export function NewDateTimeFormatter(isoDateString:any, addHour = true) { + const date = new Date(isoDateString); + if (addHour) { + date.setTime(date.getTime() + 1 * 60 * 60 * 1000); + } + const formattedDate = date.toLocaleDateString("en-US", { + year: "numeric", + month: "numeric", + day: "numeric", + hour: "2-digit", + minute: "2-digit", + // second: "2-digit", + hour12: true, + timeZone: "UTC", + }); + return formattedDate; + } \ No newline at end of file diff --git a/src/models/DataTypes.ts b/src/models/DataTypes.ts new file mode 100644 index 0000000..f98869b --- /dev/null +++ b/src/models/DataTypes.ts @@ -0,0 +1,9 @@ + +export type TableListProps = { + id?: number; + name?: string; + date?: string; + amount?: string; + payment_term?: string; + status?: boolean; +}[]; \ No newline at end of file From 408777353d25c3867a995129713c45c2bf2e8a93 Mon Sep 17 00:00:00 2001 From: victorAnumudu Date: Mon, 6 May 2024 16:52:00 +0100 Subject: [PATCH 2/2] pending loan list added --- .../Dashboard/DashboardHomeIntro.tsx | 59 +++++++++++++------ src/components/paginated-list/PendingList.tsx | 7 ++- src/core/apiRequest.ts | 9 ++- src/core/models.ts | 11 +++- src/models/DataTypes.ts | 9 --- 5 files changed, 62 insertions(+), 33 deletions(-) delete mode 100644 src/models/DataTypes.ts diff --git a/src/components/Dashboard/DashboardHomeIntro.tsx b/src/components/Dashboard/DashboardHomeIntro.tsx index 4a656c7..c32fcd7 100644 --- a/src/components/Dashboard/DashboardHomeIntro.tsx +++ b/src/components/Dashboard/DashboardHomeIntro.tsx @@ -1,8 +1,11 @@ -import React, { FC } from "react"; +import React, { FC, useState, useEffect } from "react"; import NairaBag from "../../assets/images/dashboard/naira-bag.png"; import { Button, Icons } from "../"; import { useSelector } from "react-redux"; import PendingList from "../paginated-list/PendingList"; +import { PendingTableList } from "../../core/models"; +import { NewDateTimeFormatter } from "../../lib/NewDateTimeFormatter"; +import { getUserPendingLoanList } from "../../core/apiRequest"; export interface DashBoardCardProps { title?: string; @@ -76,6 +79,29 @@ interface DashboardHomeIntroProps { const DashboardHomeIntro: FC = ({ handleNextStep, step }) => { const { userDetails } = useSelector((state:any) => state?.userDetails); // CHECKS IF USER Details are avaliable + + const [userLoanList, setUserLoanList] = useState<{loading:boolean, data:PendingTableList}>({loading: true, data:[]}) + + useEffect(()=>{ + let token = localStorage.getItem('token') + let uid = localStorage.getItem('uid') + if(!token || !uid){ + return + } + getUserPendingLoanList(uid).then(res => { + console.log('RES', res) + console.log('RES', userLoanList) + if(!res || !res.data.loans){ + setUserLoanList({loading:false, data:[]}) + return + } + setUserLoanList({loading:false, data:res?.data?.loans}) + }).catch(err => { + console.log(err) + setUserLoanList({loading:false, data:[]}) + }) + },[]) + return (
{step == 1 ? @@ -115,31 +141,34 @@ const DashboardHomeIntro: FC = ({ handleNextStep, step
} + {userLoanList.loading ? + null + :
- {({data}:any)=>( + {(data:any)=>(
- - - + + + {data.map((item:any, index:any) =>( - - - - + + + +
DateAmountPayment TermStatusAmountPayment TermStatus Action
{'item.date'}The Sliding Mr. Bones (Next Stop, Pottersville)12Malcolm Lockyer{NewDateTimeFormatter(item?.added)}{item?.loan_amount}{item?.payment_month}{item?.status}