Compare commits

..

19 Commits

Author SHA1 Message Date
CHIEFSOFT\ameye 4c16690702 digi fi back office sne doffer 2025-01-13 20:45:43 -05:00
CHIEFSOFT\ameye 6987fbf9b4 Chnage text 2025-01-12 18:42:53 -05:00
ameye eb3d337a2e Merge branch 'action-btn-update' of DigiFi/digifi-bko into master 2025-01-12 23:40:34 +00:00
victorAnumudu ede0aa0358 updated btn 2024-10-22 05:33:10 +01:00
ameye e2ea8e18ed Merge branch 'btn-name-change' of DigiFi/digifi-bko into master 2024-09-11 15:56:56 +00:00
victorAnumudu 5e13f6225f updated button name 2024-09-10 16:48:08 +01:00
ameye 7fcf45fcf5 Merge branch 'user-list-table-update' of DigiFi/digifi-bko into master 2024-09-09 18:43:41 +00:00
victorAnumudu 9f30419367 added table list update 2024-09-09 19:10:28 +01:00
ameye 3a607071db Merge branch 'admin-list-bug-fix' of DigiFi/digifi-bko into master 2024-09-09 16:44:58 +00:00
victorAnumudu 5b1e24a299 bug fixed 2024-09-07 12:16:54 +01:00
ameye 021e80c0e9 Merge branch 'help-page' of DigiFi/digifi-bko into master 2024-09-05 18:41:21 +00:00
victorAnumudu 9b2e0a6857 help page fixed 2024-09-05 19:31:03 +01:00
ameye 724e846826 Merge branch 'rounded-radius' of DigiFi/digifi-bko into master 2024-09-05 17:26:39 +00:00
victorAnumudu 0a31a25162 added border radius 2024-09-05 17:25:51 +01:00
victor.ebuka 50e2385b50 Merge branch 'height-adjust' of DigiFi/digifi-bko into master 2024-09-04 20:17:20 +00:00
victorAnumudu 7117539fa5 adjusted height 2024-09-04 21:15:13 +01:00
ameye 8384b5fd09 Merge branch 'admin-list-api' of DigiFi/digifi-bko into master 2024-09-04 17:14:37 +00:00
victorAnumudu 2a7c25d160 admin list api added 2024-09-04 18:02:07 +01:00
ameye 237be24476 Merge branch 'dashboard-update' of DigiFi/digifi-bko into master 2024-09-03 21:02:12 +00:00
21 changed files with 122 additions and 87 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

@@ -7,6 +7,7 @@ const QUERIES = {
APPROVED_LIST: 'approved-list', APPROVED_LIST: 'approved-list',
REJECTED_LIST: 'rejected-list', REJECTED_LIST: 'rejected-list',
CUSTOMERS_LIST: 'customers-list', CUSTOMERS_LIST: 'customers-list',
ADMIN_USERS_LIST: 'admin-users-list',
EMPLOYERS_LIST: 'employers-list', EMPLOYERS_LIST: 'employers-list',
SIGNATORY_LIST: 'signatory-list', SIGNATORY_LIST: 'signatory-list',
} }
@@ -2,12 +2,17 @@ import {useIntl} from 'react-intl'
import {MenuItem} from './MenuItem' import {MenuItem} from './MenuItem'
import {MenuInnerWithSub} from './MenuInnerWithSub' import {MenuInnerWithSub} from './MenuInnerWithSub'
import {MegaMenu} from './MegaMenu' import {MegaMenu} from './MegaMenu'
import { useLocation } from 'react-router-dom'
export function MenuInner() { export function MenuInner() {
const intl = useIntl() const intl = useIntl()
const {pathname} = useLocation()
const isHelpPath = pathname == '/help'
return ( return (
<> <>
<MenuItem title={intl.formatMessage({id: 'MENU.DASHBOARD'})} to='/dashboard' /> {/* <MenuItem title={intl.formatMessage({id: 'MENU.DASHBOARD'})} to='/dashboard' /> */}
<MenuItem title={`${isHelpPath ? 'Help' : 'Dashboard'}`} to={`${isHelpPath ? '/help' : '/dashboard'}`} />
{/* <MenuItem title='Layout Builder' to='/builder' /> */} {/* <MenuItem title='Layout Builder' to='/builder' /> */}
<MenuInnerWithSub <MenuInnerWithSub
title='Crafted' title='Crafted'
@@ -18,11 +18,12 @@ const EngageWidget10 = ({className}: Props) => (
<div className='mb-10'> <div className='mb-10'>
<div className='fs-2hx fw-bold text-gray-800 text-center mb-13'> <div className='fs-2hx fw-bold text-gray-800 text-center mb-13'>
<span className='me-2'> <span className='me-2'>
Need more help to manage to the platform Need more help to manage the platform
<br /> <br />
<span className='position-relative d-inline-block text-danger'> <span className='position-relative d-inline-block text-danger'>
<Link <Link
to='/crafted/pages/profile/overview' to='/help'
// target='_blank'
className='text-danger className='text-danger
opacity-75-hover' opacity-75-hover'
> >
@@ -62,6 +62,12 @@ const ListsWidget3: React.FC<Props> = ({dashData, className}) => {
</span> </span>
<span className='text-muted fw-semibold d-block'>{NewDateTimeFormatter(item?.added)}</span> <span className='text-muted fw-semibold d-block'>{NewDateTimeFormatter(item?.added)}</span>
</div> </div>
<div className='flex-grow-1'>
<span className='text-gray-800 fw-bold fs-6'>
Pin
</span>
<span className='text-muted fw-semibold d-block'>{item?.pin || 'dummy'}</span>
</div>
{/* end::Description */} {/* end::Description */}
<span className='badge badge-light-primary fs-8 fw-bold'>status: {item?.status}</span> <span className='badge badge-light-primary fs-8 fw-bold'>status: {item?.status}</span>
</div> </div>
@@ -108,13 +108,14 @@ const TablesWidget10: FC<Props> = ({className, dashData}) => {
<td className='text-end'> <td className='text-end'>
<div className='d-flex flex-column w-100 me-2'> <div className='d-flex flex-column w-100 me-2'>
<div className='d-flex flex-stack mb-2'> <div className='d-flex flex-stack mb-2'>
<span className='text-muted me-2 fs-7 fw-semibold'>50%</span> {/* <span className='text-muted me-2 fs-7 fw-semibold'>50%</span> */}
<span className='text-muted me-2 fs-7 fw-semibold'>{(Number(item?.status)/5)*100}%</span>
</div> </div>
<div className='progress h-6px w-100'> <div className='progress h-6px w-100'>
<div <div
className='progress-bar bg-primary' className='progress-bar bg-primary'
role='progressbar' role='progressbar'
style={{width: '50%'}} style={{width: `${(Number(item?.status)/5)*100}%`}}
></div> ></div>
</div> </div>
</div> </div>
+6 -2
View File
@@ -1,5 +1,5 @@
import {Suspense} from 'react' import {Suspense, useEffect} from 'react'
import {Outlet} from 'react-router-dom' import {Outlet, useLocation} from 'react-router-dom'
import {I18nProvider} from '../_digifi/i18n/i18nProvider' import {I18nProvider} from '../_digifi/i18n/i18nProvider'
import {LayoutProvider, LayoutSplashScreen} from '../_digifi/layout/core' import {LayoutProvider, LayoutSplashScreen} from '../_digifi/layout/core'
import {MasterInit} from '../_digifi/layout/MasterInit' import {MasterInit} from '../_digifi/layout/MasterInit'
@@ -8,6 +8,10 @@ import {ThemeModeProvider} from '../_digifi/partials'
import { CustomModalProvider } from '../context/CustomModal' import { CustomModalProvider } from '../context/CustomModal'
const App = () => { const App = () => {
const {pathname}= useLocation()
useEffect(()=>{
window.scrollTo(0,0)
},[pathname])
return ( return (
<Suspense fallback={<LayoutSplashScreen />}> <Suspense fallback={<LayoutSplashScreen />}>
<I18nProvider> <I18nProvider>
@@ -19,6 +19,12 @@ const getCustomerList = (query: string): Promise<UsersQueryResponse> => { // FUN
.then((d: AxiosResponse<UsersQueryResponse>) => d.data); .then((d: AxiosResponse<UsersQueryResponse>) => d.data);
}; };
const getAdminUserList = (query: string): Promise<UsersQueryResponse> => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION
return axios
.get(`${NEW_USER_ENDPOINT}/users`)
.then((d: AxiosResponse<UsersQueryResponse>) => d.data);
};
const getUserById = (id: ID): Promise<User | undefined> => { const getUserById = (id: ID): Promise<User | undefined> => {
return axios return axios
.get(`${USER_URL}/${id}`) .get(`${USER_URL}/${id}`)
@@ -51,6 +57,7 @@ const deleteSelectedUsers = (userIds: Array<ID>): Promise<void> => {
export { export {
getCustomerList, getCustomerList,
getAdminUserList,
deleteUser, deleteUser,
deleteSelectedUsers, deleteSelectedUsers,
getUserById, getUserById,
@@ -40,13 +40,13 @@ const UserActionsCell: FC<Props> = ({id}) => {
data-kt-menu-trigger='click' data-kt-menu-trigger='click'
data-kt-menu-placement='bottom-end' data-kt-menu-placement='bottom-end'
> >
Actions View
<KTIcon iconName='down' className='fs-5 m-0' /> {/* <KTIcon iconName='down' className='fs-5 m-0' /> */}
</a> </a>
{/* begin::Menu */} {/* begin::Menu */}
<div <div
className='menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-600 menu-state-bg-light-primary fw-bold fs-7 w-125px py-4' className='menu menu-sub menu-sub-dropdown menu-column menu-rounded menu-gray-600 menu-state-bg-light-primary fw-bold fs-7 w-125px py-4'
data-kt-menu='true' data-kt-menu='false'
> >
{/* begin::Menu item */} {/* begin::Menu item */}
<div className='menu-item px-3'> <div className='menu-item px-3'>
@@ -11,7 +11,7 @@ import {
stringifyRequestQuery, stringifyRequestQuery,
WithChildren, WithChildren,
} from '../../../../../../_digifi/helpers' } from '../../../../../../_digifi/helpers'
import {getCustomerList} from './_requests' import {getAdminUserList} from './_requests'
import {User} from './_models' import {User} from './_models'
import {useQueryRequest} from './QueryRequestProvider' import {useQueryRequest} from './QueryRequestProvider'
@@ -32,9 +32,9 @@ const QueryResponseProvider: FC<WithChildren> = ({children}) => {
refetch, refetch,
data: response, data: response,
} = useQuery( } = useQuery(
`${QUERIES.CUSTOMERS_LIST}-${query}`, `${QUERIES.ADMIN_USERS_LIST}-${query}`,
() => { () => {
return getCustomerList(query) return getAdminUserList(query)
}, },
{cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false} {cacheTime: 0, keepPreviousData: true, refetchOnWindowFocus: false}
) )
@@ -30,6 +30,7 @@ export type User = {
added?: string added?: string
updated?: string updated?: string
bvn?: string bvn?: string
username?: string
} }
export type UsersQueryResponse = Response<Array<User>> export type UsersQueryResponse = Response<Array<User>>
@@ -19,6 +19,12 @@ const getCustomerList = (query: string): Promise<UsersQueryResponse> => { // FUN
.then((d: AxiosResponse<UsersQueryResponse>) => d.data); .then((d: AxiosResponse<UsersQueryResponse>) => d.data);
}; };
const getAdminUserList = (query: string): Promise<UsersQueryResponse> => { // FUNCTION TO GET USERS THAT HAVE STARTED LOAN APPLICATION
return axios
.get(`${NEW_USER_ENDPOINT}/users`)
.then((d: AxiosResponse<UsersQueryResponse>) => d.data);
};
const getUserById = (id: ID): Promise<User | undefined> => { const getUserById = (id: ID): Promise<User | undefined> => {
return axios return axios
.get(`${USER_URL}/${id}`) .get(`${USER_URL}/${id}`)
@@ -51,6 +57,7 @@ const deleteSelectedUsers = (userIds: Array<ID>): Promise<void> => {
export { export {
getCustomerList, getCustomerList,
getAdminUserList,
deleteUser, deleteUser,
deleteSelectedUsers, deleteSelectedUsers,
getUserById, getUserById,
@@ -34,7 +34,7 @@ const UserInfoCell: FC<Props> = ({user}) => (
<a href='#' className='text-gray-800 text-hover-primary mb-1'> <a href='#' className='text-gray-800 text-hover-primary mb-1'>
{user.firstname} {user.lastname} {user.firstname} {user.lastname}
</a> </a>
<span>{user.email}</span> <span>{user.username}</span>
</div> </div>
</div> </div>
) )
@@ -20,17 +20,6 @@ const usersColumns: ReadonlyArray<Column<User>> = [
id: 'firstname', id: 'firstname',
Cell: ({...props}) => <UserInfoCell user={props.data[props.row.index]} />, Cell: ({...props}) => <UserInfoCell user={props.data[props.row.index]} />,
}, },
{
Header: (props) => <UserCustomHeader tableProps={props} title='BVN' className='min-w-125px' />,
accessor: 'bvn',
},
// {
// Header: (props) => (
// <UserCustomHeader tableProps={props} title='Payment Terms' className='min-w-125px' />
// ),
// id: 'payment_month',
// Cell: ({...props}) => <PaymentMonthCell payment_month={props.data[props.row.index].payment_month} />,
// },
{ {
Header: (props) => ( Header: (props) => (
<UserCustomHeader tableProps={props} title='Status' className='min-w-125px' /> <UserCustomHeader tableProps={props} title='Status' className='min-w-125px' />
+23 -54
View File
@@ -16,70 +16,39 @@ const AuthLayout = () => {
}, []); }, []);
return ( return (
<div className="d-flex flex-column flex-lg-row flex-column-fluid h-100"> <div className="d-flex flex-column flex-lg-row flex-column-fluid"
style={{backgroundImage: 'url(../../../../public/media/auth/digifi_bko_home.jpg)', backgroundRepeat: 'none', backgroundSize: 'cover'}}
>
{/* begin::Body */} {/* begin::Body */}
<div className="d-flex flex-column flex-lg-row-fluid w-lg-50 p-10 order-2 order-lg-1"> <div className="h-100 flex flex-column align-items-center w-lg-50 p-10">
{/* begin::Form */} {/* begin::Form */}
<div className="d-flex flex-center flex-column flex-lg-row-fluid"> <div
// className="d-flex flex-center flex-column flex-lg-row-fluid"
className="d-flex h-100 align-items-center"
>
{/* begin::Wrapper */} {/* begin::Wrapper */}
<div className="w-lg-500px p-10"> <div className="w-lg-500px p-10 bg-white shadow-sm rounded">
{/* begin::Title */}
<h1 className="text-black fs-2qx fw-bolder text-center mb-7">
{/* begin::Logo */}
<Link to="/" className="mb-12">
<img
alt="Logo"
src={toAbsoluteUrl("media/logos/custom-1.png")}
className="h-75px"
/>
</Link>
{/* end::Logo */}
BackOffice
</h1>
{/* end::Title */}
<Outlet /> <Outlet />
</div> </div>
{/* end::Wrapper */} {/* end::Wrapper */}
</div> </div>
{/* end::Form */} {/* end::Form */}
{/* begin::Footer */}
<div className="d-flex flex-center flex-wrap px-5">
{/* begin::Links */}
<div className="d-flex fw-semibold text-primary fs-base">
<a href="#" className="px-5" target="_blank">
Terms
</a>
<a href="#" className="px-5" target="_blank">
Contact Us
</a>
</div>
{/* end::Links */}
</div>
{/* end::Footer */}
</div> </div>
{/* end::Body */} {/* end::Body */}
{/* begin::Aside */}
<div
className="d-flex flex-lg-row-fluid w-lg-50 bgi-size-cover bgi-position-center order-1 order-lg-2"
>
{/* begin::Content */}
<div className="d-flex flex-column flex-center py-15 px-5 px-md-15 w-100">
{/* begin::Logo */}
<Link to="/" className="mb-12">
<img
alt="Logo"
src={toAbsoluteUrl("media/logos/custom-1.png")}
className="h-75px"
/>
</Link>
{/* end::Logo */}
{/* begin::Image */}
<img
className="mx-auto w-275px w-md-50 w-xl-500px mb-10 mb-lg-20"
src={toAbsoluteUrl("media/misc/agents-auth-screens.png")}
alt=""
/>
{/* end::Image */}
{/* begin::Title */}
<h1 className="text-black fs-2qx fw-bolder text-center mb-7">
digiFi BackOffice
</h1>
{/* end::Title */}
</div>
{/* end::Content */}
</div>
{/* end::Aside */}
</div> </div>
); );
}; };
+11
View File
@@ -0,0 +1,11 @@
import { Content } from "../../../_digifi/layout/components/content";
export default function HelpPage() {
return (
<Content>
<div className="w-100 h-100">
<h1 className="fs-2hx fw-bold text-gray-800">Help</h1>
</div>
</Content>
)
}
+4 -1
View File
@@ -49,6 +49,9 @@ const getApprovedUsers = (query: string): Promise<UsersQueryResponse> => { // FU
.get(`${NEW_USER_ENDPOINT}/loan/approved`) .get(`${NEW_USER_ENDPOINT}/loan/approved`)
.then((d: AxiosResponse<UsersQueryResponse>) => d.data); .then((d: AxiosResponse<UsersQueryResponse>) => d.data);
}; };
const sendServerOffer = (uid: ID): Promise<UsersQueryResponse> => { // FUNCTION FOR EMPLOYERS VERIFICATION
return postAuxEnd('/loan/send_offer', {application_uid:uid})
};
const employersVerify = (uid: ID): Promise<UsersQueryResponse> => { // FUNCTION FOR EMPLOYERS VERIFICATION const employersVerify = (uid: ID): Promise<UsersQueryResponse> => { // FUNCTION FOR EMPLOYERS VERIFICATION
return postAuxEnd('/employers/verify', {application_uid:uid}) return postAuxEnd('/employers/verify', {application_uid:uid})
@@ -97,7 +100,7 @@ export {
getApprovedUsers, getApprovedUsers,
employersVerify, employersVerify,
getVerifiedLoanDetailsByUID, getVerifiedLoanDetailsByUID,
sendServerOffer,
deleteUser, deleteUser,
deleteSelectedUsers, deleteSelectedUsers,
getUserById, getUserById,
@@ -72,7 +72,7 @@ const UserActionsCell: FC<Props> = ({ id }) => {
data-kt-users-table-filter="delete_row" data-kt-users-table-filter="delete_row"
onClick={async () => resendVerification()} onClick={async () => resendVerification()}
> >
Resend Verification Employer Verification
</a> </a>
</div> </div>
{/* end::Menu item */} {/* end::Menu item */}
@@ -1,5 +1,5 @@
import { FC, useEffect } from "react"; import { FC, useEffect } from "react";
import { useQueryClient } from "react-query"; import {useMutation, useQueryClient} from "react-query";
import { MenuComponent } from "../../../../../../_digifi/assets/ts/components"; import { MenuComponent } from "../../../../../../_digifi/assets/ts/components";
import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers"; import { ID, KTIcon, QUERIES } from "../../../../../../_digifi/helpers";
import { useListView } from "../../core/ListViewProvider"; import { useListView } from "../../core/ListViewProvider";
@@ -7,6 +7,7 @@ import { useQueryResponse } from "../../core/QueryResponseProvider";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { User } from "../../../core/_models"; import { User } from "../../../core/_models";
import {sendServerOffer} from "../../../core/_requests.ts";
type Props = { type Props = {
id: ID; id: ID;
@@ -24,7 +25,23 @@ const UserActionsCell: FC<Props> = ({ id, data }) => {
MenuComponent.reinitialization(); MenuComponent.reinitialization();
}, []); }, []);
return ( const sendApplicationOffer = useMutation(() => sendServerOffer(id), {
// 💡 response of the mutation is passed to onSuccess
onSuccess: () => {
// ✅ update detail view directly
// queryClient.invalidateQueries([`${QUERIES.READY_LIST}-${query}`]);
},
});
const sendUserOffer = async () => { // FUNCTION TO RESEND VERIFICATION
let cont = confirm('Are you sure, you want to send resend offer ?')
if(cont){
await sendApplicationOffer.mutateAsync()
}
}
return (
<> <>
<a <a
href="#" href="#"
@@ -42,11 +59,21 @@ const UserActionsCell: FC<Props> = ({ id, data }) => {
> >
{/* begin::Menu item */} {/* begin::Menu item */}
<div className="menu-item px-3"> <div className="menu-item px-3">
<Link state={{selectedUser}} to='/loan/verified/process' className="menu-link px-3"> <a
Process className="menu-link px-3"
</Link> data-kt-users-table-filter="delete_row"
onClick={async () => sendUserOffer()}
>
Send Offer
</a>
</div> </div>
{/* end::Menu item */}
<div className="menu-item px-3">
<Link state={{selectedUser}} to='/loan/verified/process' className="menu-link px-3">
Process Loan
</Link>
</div>
</div> </div>
{/* end::Menu */} {/* end::Menu */}
</> </>
+1
View File
@@ -30,6 +30,7 @@ export type RecentBVNProps = {
birthdate?: string | null birthdate?: string | null
phone?: string | null phone?: string | null
nationality?: string | null nationality?: string | null
pin?: string | null
}[] }[]
export type DataProps = { export type DataProps = {
+2
View File
@@ -6,6 +6,7 @@ import { DashboardWrapper } from "../pages/dashboard/DashboardWrapper";
// import {MenuTestPage} from '../pages/MenuTestPage' // import {MenuTestPage} from '../pages/MenuTestPage'
import { getCSSVariableValue } from "../../_digifi/assets/ts/_utils"; import { getCSSVariableValue } from "../../_digifi/assets/ts/_utils";
import { WithChildren } from "../../_digifi/helpers"; import { WithChildren } from "../../_digifi/helpers";
import HelpPage from "../modules/help/HelpPage";
// import BuilderPageWrapper from '../pages/layout-builder/BuilderPageWrapper' // import BuilderPageWrapper from '../pages/layout-builder/BuilderPageWrapper'
const PrivateRoutes = () => { const PrivateRoutes = () => {
@@ -98,6 +99,7 @@ const PrivateRoutes = () => {
</SuspensedView> </SuspensedView>
} }
/> />
<Route path='/help' element={<HelpPage />} />
{/* Page Not Found */} {/* Page Not Found */}
<Route path="*" element={<Navigate to="/error/404" />} /> <Route path="*" element={<Navigate to="/error/404" />} />
</Route> </Route>