Compare commits
19 Commits
build-bug-fix
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 37b371faf5 | |||
| 601babbcae | |||
| 7ca70d7f55 | |||
| 39c99f68bc | |||
| 21a43b9c21 | |||
| 2b1ec53131 | |||
| 1054fa0fd1 | |||
| 094b8b15d5 | |||
| b0263ae768 | |||
| 0fb267e3f4 | |||
| c686acf1e8 | |||
| 5d8d5aa2be | |||
| 5c8f96d92a | |||
| ae0500a799 | |||
| fc38378210 | |||
| 044b880726 | |||
| 28b3d85b24 | |||
| f440c5a9b9 | |||
| 4481e6b826 |
@@ -7,7 +7,7 @@ INSTAGRAM_URL=https://www.instagram.com
|
|||||||
|
|
||||||
# BACKEND END POINTS
|
# BACKEND END POINTS
|
||||||
REACT_APP_MAIN_API="https://devapi.mermsemr.com"
|
REACT_APP_MAIN_API="https://devapi.mermsemr.com"
|
||||||
# REACT_APP_MAIN_API="http://localhost:14700"
|
#REACT_APP_MAIN_API="http://localhost:14700"
|
||||||
|
|
||||||
# ENQUIRIES CONTACTS
|
# ENQUIRIES CONTACTS
|
||||||
VITE_CALL_ENDPOINT='09099000000'
|
VITE_CALL_ENDPOINT='09099000000'
|
||||||
@@ -20,4 +20,6 @@ VITE_BANK_NAME_SHORT='FCMB'
|
|||||||
# Inactivity timeout/logout AT 10MINS
|
# Inactivity timeout/logout AT 10MINS
|
||||||
REACT_APP_TIMEOUT=600000
|
REACT_APP_TIMEOUT=600000
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -18,4 +18,7 @@ VITE_BANK_NAME='First City Monument Bank'
|
|||||||
VITE_BANK_NAME_SHORT='FCMB'
|
VITE_BANK_NAME_SHORT='FCMB'
|
||||||
|
|
||||||
# Inactivity timeout/logout AT 10MINS
|
# Inactivity timeout/logout AT 10MINS
|
||||||
REACT_APP_TIMEOUT=600000
|
REACT_APP_TIMEOUT=600000
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|||||||
+5
-2
@@ -7,7 +7,7 @@ INSTAGRAM_URL=https://www.instagram.com
|
|||||||
|
|
||||||
# BACKEND END POINTS
|
# BACKEND END POINTS
|
||||||
REACT_APP_MAIN_API="https://api.mermsemr.com"
|
REACT_APP_MAIN_API="https://api.mermsemr.com"
|
||||||
#REACT_APP_MAIN_API="http://localhost:14700"
|
# REACT_APP_MAIN_API="http://localhost:14700"
|
||||||
|
|
||||||
# ENQUIRIES CONTACTS
|
# ENQUIRIES CONTACTS
|
||||||
VITE_CALL_ENDPOINT='09099000000'
|
VITE_CALL_ENDPOINT='09099000000'
|
||||||
@@ -18,4 +18,7 @@ VITE_BANK_NAME='First City Monument Bank'
|
|||||||
VITE_BANK_NAME_SHORT='FCMB'
|
VITE_BANK_NAME_SHORT='FCMB'
|
||||||
|
|
||||||
# Inactivity timeout/logout AT 10MINS
|
# Inactivity timeout/logout AT 10MINS
|
||||||
REACT_APP_TIMEOUT=600000
|
REACT_APP_TIMEOUT=600000
|
||||||
|
|
||||||
|
#CLOUDFLARE
|
||||||
|
REACT_APP_TURNSTILE_SITE_KEY=0x4AAAAAADQV82wuocFR-u5O
|
||||||
|
|||||||
+2
-2
@@ -27,9 +27,9 @@ COPY . .
|
|||||||
|
|
||||||
#RUN npm run build
|
#RUN npm run build
|
||||||
|
|
||||||
|
RUN npm run start
|
||||||
# CMD [ "npm", "run", "preview" ]
|
# CMD [ "npm", "run", "preview" ]
|
||||||
##CMD [ "npm", "run", "start" ,"--", "--host"]
|
##CMD [ "npm", "run", "start" ,"--", "--host"]
|
||||||
|
|
||||||
CMD /bin/sh ./run.sh
|
#CMD /bin/sh ./run.sh
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@reduxjs/toolkit": "^2.5.1",
|
"@reduxjs/toolkit": "^2.5.1",
|
||||||
"@tanstack/react-query": "^5.66.0",
|
"@tanstack/react-query": "^5.66.0",
|
||||||
|
"@marsidev/react-turnstile": "^1.5.2",
|
||||||
"apexcharts": "^4.5.0",
|
"apexcharts": "^4.5.0",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
"cra-template": "1.2.0",
|
"cra-template": "1.2.0",
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ const RouteLinks = {
|
|||||||
homePage: '/',
|
homePage: '/',
|
||||||
customerPage: '/customer',
|
customerPage: '/customer',
|
||||||
accountDetails: '/account-view/*',
|
accountDetails: '/account-view/*',
|
||||||
|
accountEdit:'/account-edit/*',
|
||||||
subscriptionDetails: '/subscription-view/*',
|
subscriptionDetails: '/subscription-view/*',
|
||||||
subscriptions: '/subscriptions',
|
subscriptions: '/subscriptions',
|
||||||
billings: '/billings',
|
billings: '/billings',
|
||||||
|
files_uploads: '/files-uploads',
|
||||||
recentSignup: '/recent-signup',
|
recentSignup: '/recent-signup',
|
||||||
|
recentAccount: '/recent-account',
|
||||||
loansPage: '/loans',
|
loansPage: '/loans',
|
||||||
transactionsPage: '/transactions',
|
transactionsPage: '/transactions',
|
||||||
countrySettings: '/country',
|
countrySettings: '/country',
|
||||||
|
|||||||
+11
-4
@@ -22,8 +22,10 @@ import ProductTemplatePage from "./pages/ProductTemplatePage";
|
|||||||
import CustomTemplatePage from "./pages/CustomTemplatePage";
|
import CustomTemplatePage from "./pages/CustomTemplatePage";
|
||||||
import SubscriptionDetailsPage from "./pages/SubscriptionDetailsPage";
|
import SubscriptionDetailsPage from "./pages/SubscriptionDetailsPage";
|
||||||
import CountrySettingsPage from "./pages/CountrySettingsPage";
|
import CountrySettingsPage from "./pages/CountrySettingsPage";
|
||||||
import ProductViewPage from "./pages/ProductViewPage"; // TRANSACTION DETAILS PAGE
|
import ProductViewPage from "./pages/ProductViewPage";
|
||||||
|
import FilesUploadPage from "./pages/FilesUploadPage"; // TRANSACTION DETAILS PAGE
|
||||||
|
import AccountEditpage from "./pages/AccountEditPage";
|
||||||
|
import RecentAccountsPage from "./pages/RecentAccountsPage";
|
||||||
|
|
||||||
// const Home = lazy(() => import('./pages/Home'));
|
// const Home = lazy(() => import('./pages/Home'));
|
||||||
|
|
||||||
@@ -34,22 +36,27 @@ export default function SiteRoutes() {
|
|||||||
|
|
||||||
<Route element={<UserExist/>}>
|
<Route element={<UserExist/>}>
|
||||||
<Route path={RouteLinks.homePage} element={<HomePage/>}/> {`*/HOME PAGE*/`}
|
<Route path={RouteLinks.homePage} element={<HomePage/>}/> {`*/HOME PAGE*/`}
|
||||||
|
|
||||||
|
<Route path={RouteLinks.recentAccount} element={<RecentAccountsPage/>}/> {`*/RECENT SIGNUP PAGE*/`}
|
||||||
<Route path={RouteLinks.recentSignup} element={<RecentSignupPage/>}/> {`*/RECENT SIGNUP PAGE*/`}
|
<Route path={RouteLinks.recentSignup} element={<RecentSignupPage/>}/> {`*/RECENT SIGNUP PAGE*/`}
|
||||||
<Route path={RouteLinks.subscriptions} element={<SubscriptionsPage/>}/> {`*/SUBSCRIPTIONS PAGE*/`}
|
<Route path={RouteLinks.subscriptions} element={<SubscriptionsPage/>}/> {`*/SUBSCRIPTIONS PAGE*/`}
|
||||||
<Route path={RouteLinks.customerPage} element={<CustomerPage/>}/> {`*/CUSTOMER PAGE*/`}
|
<Route path={RouteLinks.customerPage} element={<CustomerPage/>}/> {`*/CUSTOMER PAGE*/`}
|
||||||
<Route path={RouteLinks.accountDetails} element={<AccountDetailsPage/>}/> {`*/CUSTOMER PAGE*/`}
|
<Route path={RouteLinks.accountDetails} element={<AccountDetailsPage/>}/> {`*/CUSTOMER PAGE*/`}
|
||||||
|
<Route path={RouteLinks.accountEdit} element={<AccountEditpage/>}/> {`*/CUSTOMER EDIT PAGE*/`}
|
||||||
|
|
||||||
<Route path={RouteLinks.billings} element={<BillingsPage/>}/> {`*/BILLINGS PAGE*/`}
|
<Route path={RouteLinks.billings} element={<BillingsPage/>}/> {`*/BILLINGS PAGE*/`}
|
||||||
<Route path={RouteLinks.products} element={<ProductsPage/>}/> {`*/PRODUCTS PAGE*/`}
|
<Route path={RouteLinks.products} element={<ProductsPage/>}/> {`*/PRODUCTS PAGE*/`}
|
||||||
<Route path={RouteLinks.productView} element={<ProductViewPage/>}/> {`*/PRODUCTS VIEW PAGE*/`}
|
<Route path={RouteLinks.productView} element={<ProductViewPage/>}/> {`*/PRODUCTS VIEW PAGE*/`}
|
||||||
<Route path={RouteLinks.usersAdmin} element={<UsersAdminPage/>}/> {`*/ADMIN USERS PAGE*/`}
|
<Route path={RouteLinks.usersAdmin} element={<UsersAdminPage/>}/> {`*/ADMIN USERS PAGE*/`}
|
||||||
|
|
||||||
|
<Route path={RouteLinks.files_uploads} element={<FilesUploadPage/>}/> {`*/FILES PAGE*/`}
|
||||||
|
|
||||||
<Route path={RouteLinks.countrySettings} element={<CountrySettingsPage/>}/> {`*/PRODUCTS TEMPLATE PAGE*/`}
|
<Route path={RouteLinks.countrySettings} element={<CountrySettingsPage/>}/> {`*/PRODUCTS TEMPLATE PAGE*/`}
|
||||||
<Route path={RouteLinks.productTemplates} element={<ProductTemplatePage/>}/> {`*/PRODUCTS TEMPLATE PAGE*/`}
|
<Route path={RouteLinks.productTemplates} element={<ProductTemplatePage/>}/> {`*/PRODUCTS TEMPLATE PAGE*/`}
|
||||||
<Route path={RouteLinks.customTemplates} element={<CustomTemplatePage/>}/> {`*/CUSTOM TEMPLATES PAGE*/`}
|
<Route path={RouteLinks.customTemplates} element={<CustomTemplatePage/>}/> {`*/CUSTOM TEMPLATES PAGE*/`}
|
||||||
|
|
||||||
<Route path={RouteLinks.loansPage} element={<LoansPage/>}/> {`*/LOANS PAGE*/`}
|
<Route path={RouteLinks.loansPage} element={<LoansPage/>}/> {`*/LOANS PAGE*/`}
|
||||||
<Route path={RouteLinks.transaction_details_page}
|
<Route path={RouteLinks.transaction_details_page} element={<TransactionDetailsPage/>}/> {`*/TRANSACTION PAGE*/`}
|
||||||
element={<TransactionDetailsPage/>}/> {`*/TRANSACTION PAGE*/`}
|
|
||||||
<Route path={RouteLinks.subscriptionDetails} element={<SubscriptionDetailsPage/>} />
|
<Route path={RouteLinks.subscriptionDetails} element={<SubscriptionDetailsPage/>} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export default function InputText({id, name, type='text', placeholder, value, handleChange}) {
|
export default function InputText({id, name, type='text', placeholder, disabled, value, handleChange}) {
|
||||||
return (
|
return (
|
||||||
<div className='w-full h-12 overflow-hidden'>
|
<div className='w-full h-12 overflow-hidden'>
|
||||||
<input id={id} name={name} type={type} value={value} placeholder={placeholder} onChange={handleChange} className='p-2 w-full h-full text-black outline-0 ring-0 border border-slate-300 focus:border-purple-600 rounded-md' />
|
<input id={id} name={name} type={type} value={value} placeholder={placeholder} disabled={disabled} onChange={handleChange} className='p-2 w-full h-full text-black outline-0 ring-0 border border-slate-300 focus:border-purple-600 rounded-md' />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
import {Link} from 'react-router-dom'
|
||||||
|
import Icons from "../Icons";
|
||||||
|
|
||||||
|
export default function AccountBannerCom({accountInfo}) {
|
||||||
|
return <>
|
||||||
|
<div className="pb-5">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="w-full">
|
||||||
|
<h4 className="font-semibold text-lg">Account Info</h4>
|
||||||
|
</div>
|
||||||
|
<div className="w-full overflow-x-auto">
|
||||||
|
<>
|
||||||
|
<table className="py-2 w-full text-sm bg-[aliceblue] dark:bg-transparent rounded-[10px]">
|
||||||
|
<thead className="py-2 text-sm text-slate-500 text-left">
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th scope="col" className="px-2 py-2">
|
||||||
|
Firstname
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Lastname
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Username
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Email
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Country
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{(accountInfo && Object.keys(accountInfo).length > 0) ?
|
||||||
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
{/*<td className="px-2 py-2">*/}
|
||||||
|
{/* <div className="text-left">*/}
|
||||||
|
{/* <div className="text-base font-semibold">{1}</div>*/}
|
||||||
|
{/* </div>*/}
|
||||||
|
{/*</td>*/}
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.firstname}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.lastname}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.username}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.email}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.country}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
:
|
||||||
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
<td className="px-3 py-2" colSpan={6}>
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
No Record Found
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import BreadcrumbCom from "../breadcrumb/BreadcrumbCom";
|
||||||
|
import RouteLinks from "../../RouteLinks";
|
||||||
|
import { getAccountView } from "../../services/siteServices";
|
||||||
|
import queryKeys from "../../services/queryKeys";
|
||||||
|
import AccountBannerCom from "./AccountBannerCom";
|
||||||
|
import UpdateProfile from "./UpdateProfile";
|
||||||
|
import UpdatePassword from "./UpdatePassword";
|
||||||
|
|
||||||
|
|
||||||
|
export default function AccountEditCom() {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const { state } = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!state?.memberUID) {
|
||||||
|
navigate(RouteLinks.homePage, { replace: true });
|
||||||
|
}
|
||||||
|
}, [navigate, state?.memberUID]);
|
||||||
|
|
||||||
|
const { data, isFetching, isError, error } = useQuery({
|
||||||
|
queryKey: queryKeys.account_view,
|
||||||
|
queryFn: () => {
|
||||||
|
// const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
|
||||||
|
const reqData = {
|
||||||
|
member_uid: state?.memberUID,
|
||||||
|
// page,
|
||||||
|
// ...filterData
|
||||||
|
};
|
||||||
|
return getAccountView(reqData);
|
||||||
|
},
|
||||||
|
staleTime: 0, //0 mins
|
||||||
|
});
|
||||||
|
const accountsViewData = data?.data; // ACCOUNT EDIT DATA
|
||||||
|
const account_info = accountsViewData?.account;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
queryClient.refetchQueries({
|
||||||
|
queryKey: [...queryKeys.account_view],
|
||||||
|
// type: 'active',
|
||||||
|
// exact: true,
|
||||||
|
});
|
||||||
|
}, [queryClient, state?.memberUID]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full flex flex-col gap-8">
|
||||||
|
<BreadcrumbCom
|
||||||
|
title={`Account Edit [${state?.memberUID}]`}
|
||||||
|
paths={["Dashboard", "Account Edit"]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isFetching ? (
|
||||||
|
<>
|
||||||
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
|
<p className="text-slate-800">Loading...</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : isError ? (
|
||||||
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
|
<p className="text-red-500">{error.message}</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
|
<AccountBannerCom accountInfo={account_info} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-12 gap-5">
|
||||||
|
<div className="p-4 col-span-12 lg:col-span-7 xl:col-span-8 shadow border rounded-xl">
|
||||||
|
<UpdateProfile accountInfo={account_info} />
|
||||||
|
</div>
|
||||||
|
<div className="p-4 max-h-96 col-span-12 lg:col-span-5 xl:col-span-4 shadow border rounded-xl">
|
||||||
|
<UpdatePassword />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
import {Link} from 'react-router-dom'
|
||||||
|
import Icons from "../Icons";
|
||||||
|
import {useMutation} from '@tanstack/react-query'
|
||||||
|
import {Formik, Form} from 'formik'
|
||||||
|
import * as Yup from "yup";
|
||||||
|
|
||||||
|
import InputText from '../InputText'
|
||||||
|
|
||||||
|
export default function UpdatePassword() {
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
newPassword: "",
|
||||||
|
confirmPassword: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
// To get the validation schema
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
newPassword: Yup.string()
|
||||||
|
.min(6, 'must be upto 6 characters')
|
||||||
|
.max(25, 'must not exceed 25 characters')
|
||||||
|
.required("New password is required"),
|
||||||
|
|
||||||
|
confirmPassword: Yup.string()
|
||||||
|
.oneOf([Yup.ref("newPassword"), null], "Passwords do not match")
|
||||||
|
.required("Confirm password is required"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatePassword = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
if (!fields.newPassword || !fields.confirmPassword) {
|
||||||
|
throw new Error('Please provide all fields marked *')
|
||||||
|
}
|
||||||
|
// return loginUser(fields)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log(error)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
// const {jwt_token, user} = res?.data
|
||||||
|
setTimeout(() => {
|
||||||
|
updatePassword.reset()
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//FUNCTION TO HANDLE LOGIN
|
||||||
|
const handleSubmit = (values, helper) => {
|
||||||
|
updatePassword.mutate(values)
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="w-full">
|
||||||
|
<h4 className="mb-3 font-semibold text-lg">Change Password</h4>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Form>
|
||||||
|
<div className='flex flex-col gap-8 w-full'>
|
||||||
|
<div className='flex flex-col gap-6'>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>New Password</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.newPassword && props.touched.newPassword) ? props.errors.newPassword : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='newPassword'
|
||||||
|
placeholder='New Password'
|
||||||
|
name='newPassword'
|
||||||
|
type='password'
|
||||||
|
value={props.values.newPassword}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Confirm Password</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.confirmPassword && props.touched.confirmPassword) ? props.errors.confirmPassword : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='confirmPassword'
|
||||||
|
placeholder='Confirm Password'
|
||||||
|
name='confirmPassword'
|
||||||
|
type='password'
|
||||||
|
value={props.values.confirmPassword}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='flex justify-end h-10 mb-10'>
|
||||||
|
<button type='submit' disabled={updatePassword.isPending} className='px-4 h-full bg-primary text-white font-bold rounded-md'>{updatePassword.isPending ? 'loading...' : 'Update Password'}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{updatePassword.error &&
|
||||||
|
<>
|
||||||
|
<div className="w-full text-center">
|
||||||
|
<p className='text-red-500 text-sm'>{updatePassword.error.message}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
{updatePassword.success &&
|
||||||
|
<>
|
||||||
|
<div className="w-full text-center">
|
||||||
|
<p className='text-emerald-500 text-sm'>{'Password Updated Successfully'}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
|
||||||
|
import {Link} from 'react-router-dom'
|
||||||
|
import Icons from "../Icons";
|
||||||
|
import {useMutation} from '@tanstack/react-query'
|
||||||
|
import {Formik, Form} from 'formik'
|
||||||
|
import * as Yup from "yup";
|
||||||
|
|
||||||
|
import InputText from '../InputText'
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import queryKeys from '../../services/queryKeys';
|
||||||
|
|
||||||
|
import {updateUserProfile} from '../../services/siteServices'
|
||||||
|
|
||||||
|
|
||||||
|
export default function UpdateProfile({accountInfo}) {
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
firstname: accountInfo?.firstname || "",
|
||||||
|
lastname: accountInfo?.lastname || "",
|
||||||
|
account_name: accountInfo?.account_name || "",
|
||||||
|
phone_number: accountInfo?.phone_number || "",
|
||||||
|
email: accountInfo?.email || "",
|
||||||
|
address: accountInfo?.address || "",
|
||||||
|
};
|
||||||
|
|
||||||
|
// To get the validation schema
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
firstname: Yup.string().required("First name is required").min(3, 'must be upto 3 characters').max(25, 'must not exceed 25 characters'),
|
||||||
|
lastname: Yup.string().required("Last name is required").min(3, 'must be upto 3 characters').max(25, 'must not exceed 25 characters'),
|
||||||
|
account_name: Yup.string().required("Account name is required").min(3, 'must be upto 3 characters').max(25, 'must not exceed 25 characters'),
|
||||||
|
phone_number: Yup.string().required("Phone number is required").min(6, 'must be upto 6 characters').max(25, 'must not exceed 25 characters'),
|
||||||
|
email: Yup.string().email('Invalid email format').required("Email is required").max(50, 'must not exceed 50 characters'),
|
||||||
|
address: Yup.string().required("Address is required").min(10, 'must be at least 10 characters').max(255, 'must not exceed 255 characters'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateProfile = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return updateUserProfile(fields)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log(error)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
// if(res?.data?.resultCode != '0') {
|
||||||
|
// throw new Error(res?.data?.message || res?.data?.resultDescription || 'An error occurred while updating profile')
|
||||||
|
// }
|
||||||
|
queryClient.refetchQueries({
|
||||||
|
queryKey: [...queryKeys.account_view],
|
||||||
|
// type: 'active',
|
||||||
|
// exact: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
updateProfile.reset()
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//FUNCTION TO HANDLE LOGIN
|
||||||
|
const handleSubmit = (values, helper) => {
|
||||||
|
const newValues= {
|
||||||
|
member_uid: accountInfo?.uid || "",
|
||||||
|
member_account_name: values?.account_name || "",
|
||||||
|
member_firstname: values?.firstname || "",
|
||||||
|
member_full_address: values?.address || "",
|
||||||
|
member_lastname: values?.lastname || "",
|
||||||
|
member_email: values?.email || "",
|
||||||
|
member_phone: values?.phone_number || ""
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProfile.mutate(newValues)
|
||||||
|
console.log('values', newValues)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="w-full">
|
||||||
|
<h4 className="mb-3 font-semibold text-lg">Edit Your Personal Settings</h4>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Form>
|
||||||
|
<div className='flex flex-col gap-8 w-full'>
|
||||||
|
<div className='flex flex-col gap-6'>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>First Name</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.firstname && props.touched.firstname) ? props.errors.firstname : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='firstname'
|
||||||
|
placeholder='First Name'
|
||||||
|
name='firstname'
|
||||||
|
value={props.values.firstname}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Last Name</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.lastname && props.touched.lastname) ? props.errors.lastname : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='lastname'
|
||||||
|
placeholder='Last Name'
|
||||||
|
name='lastname'
|
||||||
|
value={props.values.lastname}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Account Name</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.account_name && props.touched.account_name) ? props.errors.account_name : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='account_name'
|
||||||
|
placeholder='Account Name'
|
||||||
|
name='account_name'
|
||||||
|
value={props.values.account_name}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Phone Number</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.phone_number && props.touched.phone_number) ? props.errors.phone_number : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='phone_number'
|
||||||
|
placeholder='Phone Number'
|
||||||
|
name='phone_number'
|
||||||
|
value={props.values.phone_number}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Email</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.email && props.touched.email) ? props.errors.email : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='email'
|
||||||
|
placeholder='Email'
|
||||||
|
disabled={true}
|
||||||
|
name='email'
|
||||||
|
value={props.values.email}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className='relative text-input flex flex-col gap-2'>
|
||||||
|
<p className='flex items-center gap-1'>
|
||||||
|
<label className='text-lg'>Address</label>
|
||||||
|
<span className='text-red-500 text-10'>{(props.errors.address && props.touched.address) ? props.errors.address : ''}</span>
|
||||||
|
</p>
|
||||||
|
<InputText
|
||||||
|
id='address'
|
||||||
|
placeholder='Address'
|
||||||
|
name='address'
|
||||||
|
value={props.values.address}
|
||||||
|
handleChange={props.handleChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-end h-10 mb-10'>
|
||||||
|
<button type='submit' disabled={updateProfile.isPending} className='px-4 h-full bg-primary text-white font-bold rounded-md'>{updateProfile.isPending ? 'loading...' : 'Update Profile'}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{updateProfile.error &&
|
||||||
|
<>
|
||||||
|
<div className="w-full text-center">
|
||||||
|
<p className='text-red-500 text-sm'>{updateProfile.error.message}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
{updateProfile.error &&
|
||||||
|
<>
|
||||||
|
<div className="w-full text-center">
|
||||||
|
<p className='text-emerald-500 text-sm'>{'Profile Updated Successfully'}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,80 +1,79 @@
|
|||||||
import {useEffect} from 'react'
|
import { useEffect } from "react";
|
||||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
||||||
import {useLocation, useNavigate} from 'react-router-dom'
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
|
import BreadcrumbCom from "../breadcrumb/BreadcrumbCom";
|
||||||
import RouteLinks from '../../RouteLinks'
|
import RouteLinks from "../../RouteLinks";
|
||||||
import { getAccountView } from '../../services/siteServices'
|
import { getAccountView } from "../../services/siteServices";
|
||||||
import queryKeys from '../../services/queryKeys'
|
import queryKeys from "../../services/queryKeys";
|
||||||
import CustomerAccountView from "./CustomerAccountView";
|
import CustomerAccountView from "./CustomerAccountView";
|
||||||
import AccountProfileView from "./AccountProfileView";
|
import AccountProfileView from "./AccountProfileView";
|
||||||
import CustomerSubscriptionsView from "./CustomerSubscriptionsView";
|
import CustomerSubscriptionsView from "./CustomerSubscriptionsView";
|
||||||
import CustomerPaymentsView from "./CustomerPaymentsView";
|
import CustomerPaymentsView from "./CustomerPaymentsView";
|
||||||
|
|
||||||
export default function AccountViewCom() {
|
export default function AccountViewCom() {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const { state } = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const {state} = useLocation()
|
useEffect(() => {
|
||||||
const navigate = useNavigate()
|
if (!state?.memberUID) {
|
||||||
|
navigate(RouteLinks.homePage, { replace: true });
|
||||||
|
}
|
||||||
|
}, [navigate, state?.memberUID]);
|
||||||
|
|
||||||
useEffect(()=>{
|
const { data, isFetching, isError, error } = useQuery({
|
||||||
if(!state?.memberUID){
|
queryKey: queryKeys.account_view,
|
||||||
navigate(RouteLinks.homePage, {replace: true})
|
queryFn: () => {
|
||||||
}
|
// const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
|
||||||
},[navigate, state?.memberUID])
|
const reqData = {
|
||||||
|
member_uid: state?.memberUID,
|
||||||
|
// page,
|
||||||
|
// ...filterData
|
||||||
|
};
|
||||||
|
return getAccountView(reqData);
|
||||||
|
},
|
||||||
|
staleTime: 0, //0 mins
|
||||||
|
});
|
||||||
|
const accountsViewData = data?.data; // ACCOUNT VIEW DATA
|
||||||
|
const account_info = accountsViewData?.account;
|
||||||
|
const account_profile = accountsViewData?.account_profile;
|
||||||
|
const subscriptions = accountsViewData?.subscriptions;
|
||||||
|
const payments = accountsViewData?.payments;
|
||||||
|
|
||||||
const {data, isFetching, isError, error} = useQuery({
|
useEffect(() => {
|
||||||
queryKey: queryKeys.account_view,
|
queryClient.refetchQueries({
|
||||||
queryFn: () => {
|
queryKey: [...queryKeys.account_view],
|
||||||
// const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
|
// type: 'active',
|
||||||
const reqData = {
|
// exact: true,
|
||||||
member_uid: state?.memberUID
|
});
|
||||||
// page,
|
}, [queryClient, state?.memberUID]);
|
||||||
// ...filterData
|
|
||||||
}
|
|
||||||
return getAccountView(reqData)
|
|
||||||
},
|
|
||||||
staleTime: 0 //0 mins
|
|
||||||
})
|
|
||||||
const accountsViewData = data?.data // ACCOUNT VIEW DATA
|
|
||||||
const account_info = accountsViewData?.account
|
|
||||||
const account_profile = accountsViewData?.account_profile
|
|
||||||
const subscriptions = accountsViewData?.subscriptions
|
|
||||||
const payments = accountsViewData?.payments
|
|
||||||
// console.log('DATA', payments, subscriptions)
|
|
||||||
|
|
||||||
useEffect(()=>{
|
return (
|
||||||
queryClient.refetchQueries({
|
<div className="w-full flex flex-col gap-8">
|
||||||
queryKey: [...queryKeys.account_view],
|
<BreadcrumbCom
|
||||||
// type: 'active',
|
title={`Account View [${state?.memberUID}]`}
|
||||||
// exact: true,
|
paths={["Dashboard", "Account View"]}
|
||||||
})
|
/>
|
||||||
},[queryClient, state?.memberUID])
|
|
||||||
|
|
||||||
return (
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
<div className='w-full flex flex-col gap-8'>
|
{isFetching ? (
|
||||||
<BreadcrumbCom title={`Account View [${state?.memberUID}]`} paths={['Dashboard', 'Account View']}/>
|
<>
|
||||||
|
<p className="text-slate-800">Loading...</p>
|
||||||
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
|
</>
|
||||||
{isFetching ?
|
) : isError ? (
|
||||||
<>
|
<p className="text-red-500">{error.message}</p>
|
||||||
<p className='text-slate-800'>Loading...</p>
|
) : (
|
||||||
</>
|
<>
|
||||||
: isError ?
|
<CustomerAccountView accountInfo={account_info} />
|
||||||
<p className='text-red-500'>{error.message}</p>
|
<AccountProfileView profile={account_profile} />
|
||||||
:
|
<CustomerSubscriptionsView subscriptions={subscriptions} />
|
||||||
<>
|
<CustomerPaymentsView payments={payments} />
|
||||||
<CustomerAccountView accountInfo={account_info} />
|
</>
|
||||||
<AccountProfileView profile={account_profile} />
|
)}
|
||||||
<CustomerSubscriptionsView subscriptions={subscriptions} />
|
</div>
|
||||||
<CustomerPaymentsView payments={payments} />
|
</div>
|
||||||
</>
|
);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {Link} from 'react-router-dom'
|
import {Link} from 'react-router-dom'
|
||||||
import Icons from "../Icons";
|
import Icons from "../Icons";
|
||||||
|
import RouteLinks from '../../RouteLinks';
|
||||||
|
|
||||||
export default function CustomerAccountView({accountInfo}) {
|
export default function CustomerAccountView({accountInfo}) {
|
||||||
return <>
|
return <>
|
||||||
@@ -26,7 +27,9 @@ export default function CustomerAccountView({accountInfo}) {
|
|||||||
<th scope="col" className="px-2">
|
<th scope="col" className="px-2">
|
||||||
Email
|
Email
|
||||||
</th>
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Country
|
||||||
|
</th>
|
||||||
<th scope="col" className="px-2 text-right">
|
<th scope="col" className="px-2 text-right">
|
||||||
Action
|
Action
|
||||||
</th>
|
</th>
|
||||||
@@ -60,13 +63,21 @@ export default function CustomerAccountView({accountInfo}) {
|
|||||||
<div className="text-base font-semibold">{accountInfo?.email}</div>
|
<div className="text-base font-semibold">{accountInfo?.email}</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">{accountInfo?.country}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td className="px-2 text-right">
|
<td className="px-2 text-right">
|
||||||
<div className='flex items-center justify-end gap-3 md:gap-4'>
|
<div className='flex items-center justify-end gap-3 md:gap-4'>
|
||||||
<div
|
<div
|
||||||
className='p-2 flex justify-center items-center text-slate-500 bg-white-body dark:text-white-body dark:bg-black-body rounded-md'>
|
className='p-2 flex justify-center items-center text-slate-500 bg-white-body dark:text-white-body dark:bg-black-body rounded-md'>
|
||||||
<Link
|
<Link
|
||||||
// to={`/subscription-view/63554d40-9ba1-4afe-80c2-ca147236f7ee`}
|
to={`/account-edit/${accountInfo?.uid}`}
|
||||||
|
state={{
|
||||||
|
customerID: accountInfo?.id,
|
||||||
|
memberUID: accountInfo?.uid,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Icons name='eye'/>
|
<Icons name='eye'/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {useNavigate} from 'react-router-dom'
|
|||||||
import {useMutation} from '@tanstack/react-query'
|
import {useMutation} from '@tanstack/react-query'
|
||||||
import {Formik, Form} from 'formik'
|
import {Formik, Form} from 'formik'
|
||||||
import * as Yup from "yup";
|
import * as Yup from "yup";
|
||||||
|
import {Turnstile} from '@marsidev/react-turnstile'
|
||||||
|
|
||||||
import InputText from '../InputText'
|
import InputText from '../InputText'
|
||||||
import {updateUserDetails} from "../../store/UserDetails";
|
import {updateUserDetails} from "../../store/UserDetails";
|
||||||
@@ -30,6 +31,7 @@ export default function LoginCom() {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [turnstileToken, setTurnstileToken] = useState(null)
|
||||||
|
|
||||||
const login = useMutation({
|
const login = useMutation({
|
||||||
mutationFn: (fields) => {
|
mutationFn: (fields) => {
|
||||||
@@ -53,9 +55,9 @@ export default function LoginCom() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
//FUNCTION TO HANDLE LOGIN
|
//FUNCTION TO HANDLE LOGIN
|
||||||
const handleSubmit = (values, helper) => {
|
const handleSubmit = (values) => {
|
||||||
login.mutate(values)
|
if (!turnstileToken) return
|
||||||
// handleLogin()
|
login.mutate({...values, cf_turnstile_response: turnstileToken})
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -107,9 +109,17 @@ export default function LoginCom() {
|
|||||||
/>
|
/>
|
||||||
{/* <p className='text-sm text-end font-medium text-primary'>Forget password ?</p> */}
|
{/* <p className='text-sm text-end font-medium text-primary'>Forget password ?</p> */}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-center col-12 mt-3">
|
||||||
|
<Turnstile
|
||||||
|
siteKey={process.env.REACT_APP_TURNSTILE_SITE_KEY}
|
||||||
|
onSuccess={setTurnstileToken}
|
||||||
|
onExpire={() => setTurnstileToken(null)}
|
||||||
|
onError={() => setTurnstileToken(null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className='h-10 mb-10'>
|
<div className='h-10 mb-10'>
|
||||||
<button type='submit' disabled={login.isPending}
|
<button type='submit' disabled={login.isPending || !turnstileToken}
|
||||||
className='w-full h-full bg-primary text-white font-bold rounded-md'>{login.isPending || loading ? 'loading...' : 'Login'}</button>
|
className='w-full h-full bg-primary text-white font-bold rounded-md disabled:opacity-50 disabled:cursor-not-allowed'>{login.isPending || loading ? 'loading...' : 'Login'}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{login.error &&
|
{login.error &&
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
import {useState} from 'react'
|
||||||
|
import {useQuery} from '@tanstack/react-query'
|
||||||
|
import queryKeys from '../../services/queryKeys'
|
||||||
|
|
||||||
|
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
|
||||||
|
import TablePaginatedWrapper from '../tableWrapper/TablePaginatedWrapper'
|
||||||
|
import Icons from '../Icons'
|
||||||
|
import {getFilesUpload} from '../../services/siteServices'
|
||||||
|
import getDateTimeFromDateString from '../../helpers/getDateTimeFromDateString';
|
||||||
|
|
||||||
|
export default function FileUploadCom() {
|
||||||
|
|
||||||
|
const [page, setPage] = useState(1)
|
||||||
|
const [filter, setFilter] = useState({type: '', id: ''})
|
||||||
|
const [willFilter, setWillFilter] = useState(false)
|
||||||
|
|
||||||
|
const handleFilter = ({target: {name, value}}) => {
|
||||||
|
setFilter(prev => ({...prev, [name]: value}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFilterByParams = () => {
|
||||||
|
if (filter.type && !filter.id) {
|
||||||
|
return
|
||||||
|
} else if (!filter.type) {
|
||||||
|
setPage(1)
|
||||||
|
setWillFilter(prev => !prev)
|
||||||
|
setFilter({type: '', id: ''})
|
||||||
|
} else {
|
||||||
|
setPage(1)
|
||||||
|
setWillFilter(prev => !prev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data, isFetching, isError, error} = useQuery({
|
||||||
|
queryKey: [...queryKeys.billings, page, willFilter],
|
||||||
|
queryFn: () => {
|
||||||
|
const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
|
||||||
|
const reqData = {
|
||||||
|
page,
|
||||||
|
...filterData
|
||||||
|
}
|
||||||
|
return getFilesUpload(reqData)
|
||||||
|
},
|
||||||
|
staleTime: 0 //0 mins
|
||||||
|
})
|
||||||
|
const billingData = data?.data?.file_list; // file_list
|
||||||
|
const media_server = data?.data?.media_server; // file_list
|
||||||
|
const pagination = data?.data?.pagination
|
||||||
|
debugger;
|
||||||
|
return (
|
||||||
|
<div className='w-full flex flex-col gap-8'>
|
||||||
|
<BreadcrumbCom title='Files' paths={['Dashboard', 'Files']}/>
|
||||||
|
|
||||||
|
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
|
||||||
|
{isError ?
|
||||||
|
<p className='text-red-500'>{error?.message}</p>
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
{/* filter section */}
|
||||||
|
<div className='px-2 py-2 mb-4 flex flex-col sm:flex-row flex-wrap sm:items-center gap-2'>
|
||||||
|
<Icons name='filter' className='text-3xl'/>
|
||||||
|
<div className='w-full sm:max-w-48'>
|
||||||
|
<select name='type' value={filter?.type} className='h-10 w-full p-2 rounded-md'
|
||||||
|
onChange={handleFilter}>
|
||||||
|
<option value=''>All</option>
|
||||||
|
<option value='file_group'>File Group</option>
|
||||||
|
<option value='member_id'>Member ID</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className='w-full sm:max-w-48'>
|
||||||
|
<input name='id' value={filter?.id} disabled={!filter.type}
|
||||||
|
className={`h-10 w-full p-2 rounded-md outline-none border border-black-aside ${!filter.type && 'opacity-30'}`}
|
||||||
|
onChange={handleFilter}/>
|
||||||
|
</div>
|
||||||
|
<button onClick={handleFilterByParams} disabled={filter.type && !filter.id}
|
||||||
|
className={`h-10 bg-primary px-2 py-1 rounded-md text-white font-medium sm:self-end ${(filter.type && !filter.id) && 'opacity-50'}`}>Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/* end of filter section */}
|
||||||
|
|
||||||
|
<TablePaginatedWrapper data={billingData} isFetching={isFetching} setPage={setPage}
|
||||||
|
itemsPerPage={pagination?.limit} pagination={pagination}>
|
||||||
|
{({data}) => (
|
||||||
|
<>
|
||||||
|
<table className="py-2 w-full text-sm">
|
||||||
|
<thead className="py-2 text-sm text-slate-500 text-left">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" className="px-2 py-2">
|
||||||
|
Added
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Member ID
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
File Name
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Group
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Status
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{(data && data.length > 0) ? data?.map((item, index) => {
|
||||||
|
const file_url = (media_server + "/" + item?.file_group + "/" + item?.file_uid + "/" + item.filename).toLowerCase();
|
||||||
|
return (
|
||||||
|
<tr key={index}
|
||||||
|
className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
<td className="px-2 py-2">
|
||||||
|
<div
|
||||||
|
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
|
||||||
|
<div className="text-left">
|
||||||
|
<div
|
||||||
|
className="text-base font-semibold">{getDateTimeFromDateString(item?.added)}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div
|
||||||
|
className="text-base font-semibold">{item?.member_id}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div
|
||||||
|
className="text-base font-semibold">
|
||||||
|
<a href={`${file_url}`} target='_blank'
|
||||||
|
rel="noreferrer">
|
||||||
|
{item?.filename}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div
|
||||||
|
className="text-base font-semibold">{item?.file_group}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div
|
||||||
|
className="text-base font-semibold">{item?.status}</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
:
|
||||||
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
<td className="px-3 py-2" colSpan={4}>
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
No Record Found
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</TablePaginatedWrapper>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import {useLocation} from 'react-router-dom'
|
import {useLocation} from 'react-router-dom'
|
||||||
import { useSelector } from "react-redux";
|
import {useSelector} from "react-redux";
|
||||||
import RouteLinks from "../../../RouteLinks";
|
import RouteLinks from "../../../RouteLinks";
|
||||||
import DummyLogo from "../../DummyLogo";
|
import DummyLogo from "../../DummyLogo";
|
||||||
import MainBtn from "../../MainBtn";
|
import MainBtn from "../../MainBtn";
|
||||||
@@ -17,7 +17,7 @@ export default function DashboardAside() {
|
|||||||
|
|
||||||
const {setLogoutModal, handleActiveMenu} = GeneralLayoutContext()
|
const {setLogoutModal, handleActiveMenu} = GeneralLayoutContext()
|
||||||
|
|
||||||
const {userDetails:{username, email}} = useSelector((state) => state.userDetails) // GETS LOGGED IN USER
|
const {userDetails: {username, email}} = useSelector((state) => state.userDetails) // GETS LOGGED IN USER
|
||||||
// const {role}= userDetails
|
// const {role}= userDetails
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -151,11 +151,13 @@ export default function DashboardAside() {
|
|||||||
const asideNavLinks = [
|
const asideNavLinks = [
|
||||||
{name: 'Dashboard', status: 1, icon: 'dashboard', to: RouteLinks.homePage},
|
{name: 'Dashboard', status: 1, icon: 'dashboard', to: RouteLinks.homePage},
|
||||||
{
|
{
|
||||||
name: 'Deployments', title: 'Activities', status: 1, icon: 'arrow-right', subLinks: [
|
name: 'Front Office', title: 'Activities', status: 1, icon: 'arrow-right', subLinks: [
|
||||||
{name: 'Recent Signup', status: 1, icon: 'dot', to: RouteLinks.recentSignup},
|
{name: 'Recent Signup', status: 1, icon: 'dot', to: RouteLinks.recentSignup},
|
||||||
|
{name: 'Recent Accounts(30)', status: 1, icon: 'dot', to: RouteLinks.recentAccount},
|
||||||
{name: 'Provisions', status: 1, icon: 'dot', to: RouteLinks.subscriptions},
|
{name: 'Provisions', status: 1, icon: 'dot', to: RouteLinks.subscriptions},
|
||||||
{name: 'Customers', status: 1, icon: 'dot', to: RouteLinks.customerPage},
|
{name: 'Customers', status: 1, icon: 'dot', to: RouteLinks.customerPage},
|
||||||
{name: 'Billings', status: 1, icon: 'dot', to: RouteLinks.billings},
|
{name: 'Billings', status: 1, icon: 'dot', to: RouteLinks.billings},
|
||||||
|
{name: 'Files & Uploads', status: 1, icon: 'dot', to: RouteLinks.files_uploads},
|
||||||
{
|
{
|
||||||
name: 'Configurations', status: 1, icon: 'arrow-right', subLinks: [
|
name: 'Configurations', status: 1, icon: 'arrow-right', subLinks: [
|
||||||
{name: 'Country', status: 1, icon: 'dot', to: RouteLinks.countrySettings},
|
{name: 'Country', status: 1, icon: 'dot', to: RouteLinks.countrySettings},
|
||||||
|
|||||||
@@ -1,86 +1,144 @@
|
|||||||
import React from 'react'
|
import React from "react";
|
||||||
import {Link} from 'react-router-dom'
|
import { Link } from "react-router-dom";
|
||||||
import Img from '../../../assets/user_avatar.jpg'
|
import Img from "../../../assets/user_avatar.jpg";
|
||||||
import CustomCounter from '../../CustomCounter'
|
import CustomCounter from "../../CustomCounter";
|
||||||
|
|
||||||
export default function RecentPaymentsBar({data, isFetching, isError, error}) {
|
export default function RecentPaymentsBar({
|
||||||
|
data,
|
||||||
const recentPayment = data?.data?.recent_payment_summary
|
isFetching,
|
||||||
const recentLogin = data?.data?.recent_login
|
isError,
|
||||||
|
error,
|
||||||
|
}) {
|
||||||
|
const recentPayment = data?.data?.recent_payment_summary;
|
||||||
|
const recentLogin = data?.data?.recent_login;
|
||||||
|
const systemList = data?.data?.system_url;
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='h-full p-2 sm:p-4 large:p-8 flex flex-col gap-16 aside-scroll-design'>
|
return (
|
||||||
<div className='flex flex-col gap-4'>
|
<div className="h-full p-2 sm:p-4 large:p-8 flex flex-col gap-16 aside-scroll-design">
|
||||||
<p className='text-base text-white-body font-bold'>Recent Payments [7 days]</p>
|
<div className="flex flex-col gap-4">
|
||||||
{isFetching ?
|
<p className="text-base text-white-body font-bold">
|
||||||
<div className='w-full flex justify-center'>
|
Recent Payments [7 days]
|
||||||
<div className="w-6 h-6 border-2 border-gray-300 border-b-gray-500 rounded-full animate-spin"></div>
|
</p>
|
||||||
</div>
|
{isFetching ? (
|
||||||
:
|
<div className="w-full flex justify-center">
|
||||||
isError ?
|
<div className="w-6 h-6 border-2 border-gray-300 border-b-gray-500 rounded-full animate-spin"></div>
|
||||||
<p className='text-base text-white-body font-bold'>{error?.message}</p>
|
</div>
|
||||||
:
|
) : isError ? (
|
||||||
<div className='grid grid-cols-2 gap-4 sm:gap-6 large:gap-8'>
|
<p className="text-base text-white-body font-bold">
|
||||||
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
|
{error?.message}
|
||||||
<p className='text-base font-bold text-white-body'>
|
</p>
|
||||||
<CustomCounter targetNumber={recentPayment?.approved} timeInSeconds={1} />
|
) : (
|
||||||
</p>
|
<div className="grid grid-cols-2 gap-4 sm:gap-6 large:gap-8">
|
||||||
<p className='text-sm text-slate-500'>Approved</p>
|
<div className="p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed">
|
||||||
</div>
|
<p className="text-base font-bold text-white-body">
|
||||||
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
|
<CustomCounter
|
||||||
<p className='text-base font-bold text-white-body'>
|
targetNumber={recentPayment?.approved}
|
||||||
<CustomCounter targetNumber={recentPayment?.verified} timeInSeconds={1} />
|
timeInSeconds={1}
|
||||||
</p>
|
/>
|
||||||
<p className='text-sm text-slate-500'>Verified</p>
|
</p>
|
||||||
</div>
|
<p className="text-sm text-slate-500">Approved</p>
|
||||||
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
|
|
||||||
<p className='text-base font-bold text-white-body'>
|
|
||||||
<CustomCounter targetNumber={recentPayment?.failed} timeInSeconds={1} />
|
|
||||||
</p>
|
|
||||||
<p className='text-sm text-slate-500'>Failed</p>
|
|
||||||
</div>
|
|
||||||
<div className='p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed'>
|
|
||||||
<p className='text-base font-bold text-white-body'>
|
|
||||||
<CustomCounter targetNumber={recentPayment?.total} timeInSeconds={1} />
|
|
||||||
</p>
|
|
||||||
<p className='text-sm text-slate-500'>Total</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<div className='overflow-y-auto h-full flex flex-col gap-4'>
|
<div className="p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed">
|
||||||
<p className='text-base text-white-body font-bold'>Recent Login</p>
|
<p className="text-base font-bold text-white-body">
|
||||||
{isFetching ?
|
<CustomCounter
|
||||||
<div className='w-full flex justify-center'>
|
targetNumber={recentPayment?.verified}
|
||||||
<div className="w-6 h-6 border-2 border-gray-300 border-b-gray-500 rounded-full animate-spin"></div>
|
timeInSeconds={1}
|
||||||
</div>
|
/>
|
||||||
:
|
</p>
|
||||||
isError ?
|
<p className="text-sm text-slate-500">Verified</p>
|
||||||
<p className='text-base text-white-body font-bold'>{error?.message}</p>
|
|
||||||
:
|
|
||||||
<div className='flex flex-col gap-4'>
|
|
||||||
{recentLogin.map((item, index)=> {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
to={`/account-view/${item?.member_uid}`}
|
|
||||||
state={{customerID: item?.id, memberUID: item?.member_uid}}
|
|
||||||
key={index}
|
|
||||||
className='flex gap-3 items-center'
|
|
||||||
>
|
|
||||||
<div className='px-4 py-2 bg-[#0E172E] rounded-md'>
|
|
||||||
<img src={Img} className='w-8' alt="Order" />
|
|
||||||
</div>
|
|
||||||
<div className='flex-col'>
|
|
||||||
<p className='text-base font-bold text-white-body'>{item.firstname} {item.lastname}</p>
|
|
||||||
<p className='text-sm text-slate-500'>{item.username}</p>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed">
|
||||||
)
|
<p className="text-base font-bold text-white-body">
|
||||||
|
<CustomCounter
|
||||||
|
targetNumber={recentPayment?.failed}
|
||||||
|
timeInSeconds={1}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-slate-500">Failed</p>
|
||||||
|
</div>
|
||||||
|
<div className="p-2 sm:p-3 large:p-4 flex flex-col border border-slate-500 border-dashed">
|
||||||
|
<p className="text-base font-bold text-white-body">
|
||||||
|
<CustomCounter
|
||||||
|
targetNumber={recentPayment?.total}
|
||||||
|
timeInSeconds={1}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-slate-500">Total</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="overflow-y-auto h-full flex flex-col gap-4">
|
||||||
|
<p className="text-base text-white-body font-bold">Systems</p>
|
||||||
|
{isFetching ? (
|
||||||
|
<div className="w-full flex justify-center">
|
||||||
|
<div className="w-6 h-6 border-2 border-gray-300 border-b-gray-500 rounded-full animate-spin"></div>
|
||||||
|
</div>
|
||||||
|
) : isError ? (
|
||||||
|
<p className="text-base text-white-body font-bold">
|
||||||
|
{error?.message}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
{systemList.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={item.url}
|
||||||
|
key={index}
|
||||||
|
target="_blank"
|
||||||
|
className="flex gap-3 items-center"
|
||||||
|
>
|
||||||
|
<div className="px-4 py-2 bg-[#0E172E] rounded-md">
|
||||||
|
<img src={Img} className="w-8" alt="Order" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-col">
|
||||||
|
<p className="text-base font-bold text-white-body">
|
||||||
|
{item.name}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-slate-500">{item.url}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="overflow-y-auto h-full flex flex-col gap-4">
|
||||||
|
<p className="text-base text-white-body font-bold">Recent Login</p>
|
||||||
|
{isFetching ? (
|
||||||
|
<div className="w-full flex justify-center">
|
||||||
|
<div className="w-6 h-6 border-2 border-gray-300 border-b-gray-500 rounded-full animate-spin"></div>
|
||||||
|
</div>
|
||||||
|
) : isError ? (
|
||||||
|
<p className="text-base text-white-body font-bold">
|
||||||
|
{error?.message}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
{recentLogin.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={`/account-view/${item?.member_uid}`}
|
||||||
|
state={{ customerID: item?.id, memberUID: item?.member_uid }}
|
||||||
|
key={index}
|
||||||
|
className="flex gap-3 items-center"
|
||||||
|
>
|
||||||
|
<div className="px-4 py-2 bg-[#0E172E] rounded-md">
|
||||||
|
<img src={Img} className="w-8" alt="Order" />
|
||||||
|
</div>
|
||||||
|
<div className="flex-col">
|
||||||
|
<p className="text-base font-bold text-white-body">
|
||||||
|
{item.firstname} {item.lastname}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-slate-500">{item.username}</p>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,203 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import queryKeys from "../../services/queryKeys";
|
||||||
|
|
||||||
|
import BreadcrumbCom from "../breadcrumb/BreadcrumbCom";
|
||||||
|
import TablePaginatedWrapper from "../tableWrapper/TablePaginatedWrapper";
|
||||||
|
import Icons from "../Icons";
|
||||||
|
import { getRecentAccount } from "../../services/siteServices";
|
||||||
|
import getDateTimeFromDateString from "../../helpers/getDateTimeFromDateString";
|
||||||
|
import {Link} from 'react-router-dom';
|
||||||
|
|
||||||
|
|
||||||
|
export default function RecentAccounts() {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [filter, setFilter] = useState({ type: "", id: "" });
|
||||||
|
const [willFilter, setWillFilter] = useState(false);
|
||||||
|
|
||||||
|
const handleFilter = ({ target: { name, value } }) => {
|
||||||
|
setFilter((prev) => ({ ...prev, [name]: value }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFilterByParams = () => {
|
||||||
|
if (filter.type && !filter.id) {
|
||||||
|
return;
|
||||||
|
} else if (!filter.type) {
|
||||||
|
setPage(1);
|
||||||
|
setWillFilter((prev) => !prev);
|
||||||
|
setFilter({ type: "", id: "" });
|
||||||
|
} else {
|
||||||
|
setPage(1);
|
||||||
|
setWillFilter((prev) => !prev);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data, isFetching, isError, error } = useQuery({
|
||||||
|
queryKey: [...queryKeys.recent_account, page, willFilter],
|
||||||
|
queryFn: () => {
|
||||||
|
const filterData = filter?.type ? { [filter?.type]: filter.id } : {};
|
||||||
|
const reqData = {
|
||||||
|
page,
|
||||||
|
...filterData,
|
||||||
|
};
|
||||||
|
return getRecentAccount(reqData);
|
||||||
|
},
|
||||||
|
staleTime: 0, //0 mins
|
||||||
|
});
|
||||||
|
const recentSignupData = data?.data?.members; // BILLINGS LIST
|
||||||
|
const pagination = data?.data?.pagination;
|
||||||
|
// console.log('DATA', data?.data)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full flex flex-col gap-8">
|
||||||
|
<BreadcrumbCom
|
||||||
|
title="Recent Accounts"
|
||||||
|
paths={["Dashboard", "Recent Acc"]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
|
{isError ? (
|
||||||
|
<p className="text-red-500">{error?.message}</p>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{/* filter section */}
|
||||||
|
<div className="px-2 py-2 mb-4 flex flex-col sm:flex-row flex-wrap sm:items-center gap-2">
|
||||||
|
<Icons name="filter" className="text-3xl" />
|
||||||
|
<div className="w-full sm:max-w-48">
|
||||||
|
<select
|
||||||
|
name="type"
|
||||||
|
value={filter?.type}
|
||||||
|
className="h-10 w-full p-2 rounded-md"
|
||||||
|
onChange={handleFilter}
|
||||||
|
>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="username">Username</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full sm:max-w-48">
|
||||||
|
<input
|
||||||
|
name="id"
|
||||||
|
value={filter?.id}
|
||||||
|
disabled={!filter.type}
|
||||||
|
className={`h-10 w-full p-2 rounded-md outline-none border border-black-aside ${!filter.type && "opacity-30"}`}
|
||||||
|
onChange={handleFilter}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleFilterByParams}
|
||||||
|
disabled={filter.type && !filter.id}
|
||||||
|
className={`h-10 bg-primary px-2 py-1 rounded-md text-white font-medium sm:self-end ${filter.type && !filter.id && "opacity-50"}`}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{/* end of filter section */}
|
||||||
|
|
||||||
|
<TablePaginatedWrapper
|
||||||
|
data={recentSignupData}
|
||||||
|
isFetching={isFetching}
|
||||||
|
setPage={setPage}
|
||||||
|
itemsPerPage={pagination?.limit}
|
||||||
|
pagination={pagination}
|
||||||
|
>
|
||||||
|
{({ data }) => (
|
||||||
|
<>
|
||||||
|
<table className="py-2 w-full text-sm">
|
||||||
|
<thead className="py-2 text-sm text-slate-500 text-left">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" className="px-2 py-2">
|
||||||
|
Added
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
User Name /Email
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Country
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Action
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{data && data.length > 0 ? (
|
||||||
|
data?.map((item, index) => (
|
||||||
|
<tr
|
||||||
|
key={index}
|
||||||
|
className="py-2 border-t border-dashed border-slate-300"
|
||||||
|
>
|
||||||
|
<td className="px-2 py-2">
|
||||||
|
<div className="w-full min-w-48 flex items-center gap-2 whitespace-nowrap">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{getDateTimeFromDateString(item?.added)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.username}
|
||||||
|
</div>
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.email}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.firstname} {item?.lastname}
|
||||||
|
</div>
|
||||||
|
{/* <div className="font-normal text-gray-500">{item?.external_url}</div> */}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.country}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td className="px-2 text-right">
|
||||||
|
<div className="flex items-center justify-end gap-3 md:gap-4">
|
||||||
|
<div className="p-2 flex justify-center items-center text-slate-500 bg-white-body dark:text-white-body dark:bg-black-body rounded-md">
|
||||||
|
<Link
|
||||||
|
to={`/account-view/${item?.member_uid}`}
|
||||||
|
state={{
|
||||||
|
customerID: item?.id,
|
||||||
|
memberUID: item?.member_uid,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icons name="eye" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
<td className="px-3 py-2" colSpan={4}>
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
No Record Found
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</TablePaginatedWrapper>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,146 +1,203 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from "react";
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import queryKeys from '../../services/queryKeys'
|
import queryKeys from "../../services/queryKeys";
|
||||||
|
|
||||||
import BreadcrumbCom from '../breadcrumb/BreadcrumbCom'
|
import BreadcrumbCom from "../breadcrumb/BreadcrumbCom";
|
||||||
import TablePaginatedWrapper from '../tableWrapper/TablePaginatedWrapper'
|
import TablePaginatedWrapper from "../tableWrapper/TablePaginatedWrapper";
|
||||||
import Icons from '../Icons'
|
import Icons from "../Icons";
|
||||||
import { getRecentSignup } from '../../services/siteServices'
|
import { getRecentSignup } from "../../services/siteServices";
|
||||||
import getDateTimeFromDateString from '../../helpers/getDateTimeFromDateString'
|
import getDateTimeFromDateString from "../../helpers/getDateTimeFromDateString";
|
||||||
// import formatNumber from '../../helpers/formatNumber'
|
import {Link} from 'react-router-dom';
|
||||||
// import formatNumber from '../../helpers/formatNumber'
|
|
||||||
// import Avatar from '../../assets/user_avatar.jpg'
|
|
||||||
|
|
||||||
|
|
||||||
export default function RecentSignup() {
|
export default function RecentSignup() {
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [filter, setFilter] = useState({ type: "", id: "" });
|
||||||
|
const [willFilter, setWillFilter] = useState(false);
|
||||||
|
|
||||||
const [page, setPage] = useState(1)
|
const handleFilter = ({ target: { name, value } }) => {
|
||||||
const [filter, setFilter] = useState({type: '', id: ''})
|
setFilter((prev) => ({ ...prev, [name]: value }));
|
||||||
const [willFilter, setWillFilter] = useState(false)
|
};
|
||||||
|
|
||||||
const handleFilter = ({target:{name, value}}) => {
|
const handleFilterByParams = () => {
|
||||||
setFilter(prev => ({...prev, [name]:value}))
|
if (filter.type && !filter.id) {
|
||||||
|
return;
|
||||||
|
} else if (!filter.type) {
|
||||||
|
setPage(1);
|
||||||
|
setWillFilter((prev) => !prev);
|
||||||
|
setFilter({ type: "", id: "" });
|
||||||
|
} else {
|
||||||
|
setPage(1);
|
||||||
|
setWillFilter((prev) => !prev);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleFilterByParams = () => {
|
const { data, isFetching, isError, error } = useQuery({
|
||||||
if(filter.type && !filter.id){
|
queryKey: [...queryKeys.recent_signup, page, willFilter],
|
||||||
return
|
queryFn: () => {
|
||||||
}else if(!filter.type){
|
const filterData = filter?.type ? { [filter?.type]: filter.id } : {};
|
||||||
setPage(1)
|
const reqData = {
|
||||||
setWillFilter(prev => !prev)
|
page,
|
||||||
setFilter({type: '', id: ''})
|
...filterData,
|
||||||
}else{
|
};
|
||||||
setPage(1)
|
return getRecentSignup(reqData);
|
||||||
setWillFilter(prev => !prev)
|
},
|
||||||
}
|
staleTime: 0, //0 mins
|
||||||
}
|
});
|
||||||
|
const recentSignupData = data?.data?.members; // BILLINGS LIST
|
||||||
|
const pagination = data?.data?.pagination;
|
||||||
|
// console.log('DATA', data?.data)
|
||||||
|
|
||||||
const {data, isFetching, isError, error} = useQuery({
|
return (
|
||||||
queryKey: [...queryKeys.recent_signup, page, willFilter],
|
<div className="w-full flex flex-col gap-8">
|
||||||
queryFn: () => {
|
<BreadcrumbCom
|
||||||
const filterData = filter?.type ? {[filter?.type]: filter.id} : {}
|
title="Signup Started Report"
|
||||||
const reqData = {
|
paths={["Dashboard", "Recent Acc"]}
|
||||||
page,
|
/>
|
||||||
...filterData
|
|
||||||
}
|
|
||||||
return getRecentSignup(reqData)
|
|
||||||
},
|
|
||||||
staleTime: 0 //0 mins
|
|
||||||
})
|
|
||||||
const recentSignupData = data?.data?.payments // BILLINGS LIST
|
|
||||||
const pagination = data?.data?.pagination
|
|
||||||
// console.log('DATA', data?.data)
|
|
||||||
|
|
||||||
return (
|
<div className="box bg-white dark:bg-black-box text-black-body dark:text-white-body">
|
||||||
<div className='w-full flex flex-col gap-8'>
|
{isError ? (
|
||||||
<BreadcrumbCom title='Recent Signup' paths={['Dashboard', 'Recent Acc']} />
|
<p className="text-red-500">{error?.message}</p>
|
||||||
|
) : (
|
||||||
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
|
<>
|
||||||
{ isError ?
|
{/* filter section */}
|
||||||
<p className='text-red-500'>{error?.message}</p>
|
<div className="px-2 py-2 mb-4 flex flex-col sm:flex-row flex-wrap sm:items-center gap-2">
|
||||||
:
|
<Icons name="filter" className="text-3xl" />
|
||||||
<>
|
<div className="w-full sm:max-w-48">
|
||||||
{/* filter section */}
|
<select
|
||||||
<div className='px-2 py-2 mb-4 flex flex-col sm:flex-row flex-wrap sm:items-center gap-2'>
|
name="type"
|
||||||
<Icons name='filter' className='text-3xl' />
|
value={filter?.type}
|
||||||
<div className='w-full sm:max-w-48'>
|
className="h-10 w-full p-2 rounded-md"
|
||||||
<select name='type' value={filter?.type} className='h-10 w-full p-2 rounded-md' onChange={handleFilter}>
|
onChange={handleFilter}
|
||||||
<option value=''>All</option>
|
>
|
||||||
<option value='name'>Name</option>
|
<option value="">All</option>
|
||||||
</select>
|
<option value="username">Username</option>
|
||||||
</div>
|
</select>
|
||||||
<div className='w-full sm:max-w-48'>
|
</div>
|
||||||
<input name='id' value={filter?.id} disabled={!filter.type} className={`h-10 w-full p-2 rounded-md outline-none border border-black-aside ${!filter.type && 'opacity-30'}`} onChange={handleFilter} />
|
<div className="w-full sm:max-w-48">
|
||||||
</div>
|
<input
|
||||||
<button onClick={handleFilterByParams} disabled={filter.type && !filter.id} className={`h-10 bg-primary px-2 py-1 rounded-md text-white font-medium sm:self-end ${(filter.type && !filter.id) && 'opacity-50'}`}>Submit</button>
|
name="id"
|
||||||
</div>
|
value={filter?.id}
|
||||||
{/* end of filter section */}
|
disabled={!filter.type}
|
||||||
|
className={`h-10 w-full p-2 rounded-md outline-none border border-black-aside ${!filter.type && "opacity-30"}`}
|
||||||
<TablePaginatedWrapper data={recentSignupData} isFetching={isFetching} setPage={setPage} itemsPerPage={pagination?.limit} pagination={pagination}>
|
onChange={handleFilter}
|
||||||
{({ data }) => (
|
/>
|
||||||
<>
|
</div>
|
||||||
<table className="py-2 w-full text-sm">
|
<button
|
||||||
<thead className="py-2 text-sm text-slate-500 text-left">
|
onClick={handleFilterByParams}
|
||||||
<tr>
|
disabled={filter.type && !filter.id}
|
||||||
<th scope="col" className="px-2 py-2">
|
className={`h-10 bg-primary px-2 py-1 rounded-md text-white font-medium sm:self-end ${filter.type && !filter.id && "opacity-50"}`}
|
||||||
Added
|
>
|
||||||
</th>
|
Submit
|
||||||
<th scope="col" className="px-2">
|
</button>
|
||||||
Option Name
|
|
||||||
</th>
|
|
||||||
<th scope="col" className="px-2 text-right">
|
|
||||||
Amount
|
|
||||||
</th>
|
|
||||||
<th scope="col" className="px-2 text-right">
|
|
||||||
Status
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{(data && data.length > 0) ? data?.map((item, index) => (
|
|
||||||
<tr key={index} className="py-2 border-t border-dashed border-slate-300">
|
|
||||||
<td className="px-2 py-2">
|
|
||||||
<div className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
|
|
||||||
<div className="text-left">
|
|
||||||
<div className="text-base font-semibold">{getDateTimeFromDateString(item?.added)}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2">
|
|
||||||
<div className="text-left">
|
|
||||||
<div className="text-base font-semibold">{item?.option_name}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2">
|
|
||||||
<div className="text-right">
|
|
||||||
<div className="text-base font-semibold">${item?.amount}</div>
|
|
||||||
{/* <div className="font-normal text-gray-500">{item?.external_url}</div> */}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-2">
|
|
||||||
<div className="text-right">
|
|
||||||
<div className="text-base font-semibold">{item?.status}</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))
|
|
||||||
:
|
|
||||||
<tr className="py-2 border-t border-dashed border-slate-300">
|
|
||||||
<td className="px-3 py-2" colSpan={4}>
|
|
||||||
<div className="flex justify-center items-center">
|
|
||||||
No Record Found
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</TablePaginatedWrapper>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/* end of filter section */}
|
||||||
)
|
|
||||||
}
|
<TablePaginatedWrapper
|
||||||
|
data={recentSignupData}
|
||||||
|
isFetching={isFetching}
|
||||||
|
setPage={setPage}
|
||||||
|
itemsPerPage={pagination?.limit}
|
||||||
|
pagination={pagination}
|
||||||
|
>
|
||||||
|
{({ data }) => (
|
||||||
|
<>
|
||||||
|
<table className="py-2 w-full text-sm">
|
||||||
|
<thead className="py-2 text-sm text-slate-500 text-left">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" className="px-2 py-2">
|
||||||
|
Signup Stareted Added
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2">
|
||||||
|
Email
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="px-2 text-right">
|
||||||
|
Status
|
||||||
|
</th>
|
||||||
|
{/* <th scope="col" className="px-2 text-right">
|
||||||
|
Action
|
||||||
|
</th> */}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{data && data.length > 0 ? (
|
||||||
|
data?.map((item, index) => (
|
||||||
|
<tr
|
||||||
|
key={index}
|
||||||
|
className="py-2 border-t border-dashed border-slate-300"
|
||||||
|
>
|
||||||
|
<td className="px-2 py-2">
|
||||||
|
<div className="w-full min-w-48 flex items-center gap-2 whitespace-nowrap">
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{getDateTimeFromDateString(item?.added)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-left">
|
||||||
|
{/* <div className="text-base font-semibold">
|
||||||
|
{item?.username}
|
||||||
|
</div> */}
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.email}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.firstname} {item?.lastname}
|
||||||
|
</div>
|
||||||
|
{/* <div className="font-normal text-gray-500">{item?.external_url}</div> */}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="px-2">
|
||||||
|
<div className="text-right">
|
||||||
|
<div className="text-base font-semibold">
|
||||||
|
{item?.status}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{/* <td className="px-2 text-right">
|
||||||
|
<div className="flex items-center justify-end gap-3 md:gap-4">
|
||||||
|
<div className="p-2 flex justify-center items-center text-slate-500 bg-white-body dark:text-white-body dark:bg-black-body rounded-md">
|
||||||
|
<Link
|
||||||
|
to={`/account-view/${item?.member_uid}`}
|
||||||
|
state={{
|
||||||
|
customerID: item?.id,
|
||||||
|
memberUID: item?.member_uid,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icons name="eye" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td> */}
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr className="py-2 border-t border-dashed border-slate-300">
|
||||||
|
<td className="px-3 py-2" colSpan={4}>
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
No Record Found
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</TablePaginatedWrapper>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -190,8 +190,8 @@ export default function SubscriptionViewCom() {
|
|||||||
|
|
||||||
|
|
||||||
<div className="text-base font-semibold">
|
<div className="text-base font-semibold">
|
||||||
<br/><span>Template :</span> {selectedSubscription?.product_template}
|
<br/><span>TM :</span> - {selectedSubscription?.template_name} - {selectedSubscription?.product_template} - {selectedSubscription?.flavor}
|
||||||
<br/><span>Custom :</span> {selectedSubscription?.custom_template}
|
<br/><span>CS :</span> {selectedSubscription?.custom_template}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import AccountEditCom from "../components/account_edit/AccountEditCom";
|
||||||
|
export default function AccountEditPage() {
|
||||||
|
return (
|
||||||
|
<AccountEditCom />
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import FileUploadCom from "../components/file_uploads/FileUploadCom";
|
||||||
|
|
||||||
|
export default function FilesUploadPage() {
|
||||||
|
return (
|
||||||
|
<FileUploadCom />
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import RecentAccounts from "../components/recent_accounts/RecentAccounts";
|
||||||
|
|
||||||
|
export default function RecentAccountsPage() {
|
||||||
|
return (
|
||||||
|
<RecentAccounts />
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -16,10 +16,12 @@ const queryKeys = {
|
|||||||
billings: ['billings'],
|
billings: ['billings'],
|
||||||
right_sidebar: ['right_sidebar'],
|
right_sidebar: ['right_sidebar'],
|
||||||
recent_signup: ['recent_signup'],
|
recent_signup: ['recent_signup'],
|
||||||
|
recent_account: ['recent_account'],
|
||||||
products: ['products'],
|
products: ['products'],
|
||||||
products_template: ['products_template'],
|
products_template: ['products_template'],
|
||||||
custom_template: ['custom_template'],
|
custom_template: ['custom_template'],
|
||||||
account_view: ['account_view'],
|
account_view: ['account_view'],
|
||||||
|
account_edit: ['account_edit'],
|
||||||
subscriptions_view: ['subscriptions_view'],
|
subscriptions_view: ['subscriptions_view'],
|
||||||
users_admin: ['users_admin'],
|
users_admin: ['users_admin'],
|
||||||
country_list: ['country_list'],
|
country_list: ['country_list'],
|
||||||
|
|||||||
@@ -88,6 +88,12 @@ export const getBillings = (reqData) => {
|
|||||||
return getAuxEnd(`/billings`, postData)
|
return getAuxEnd(`/billings`, postData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET FILES
|
||||||
|
export const getFilesUpload = (reqData) => {
|
||||||
|
const postData = { ...reqData }
|
||||||
|
return getAuxEnd(`/file-uploads`, postData)
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET SUBSCRIPTIONS
|
// FUNCTION TO GET SUBSCRIPTIONS
|
||||||
export const getSubscriptions = (reqData) => {
|
export const getSubscriptions = (reqData) => {
|
||||||
const postData = { ...reqData }
|
const postData = { ...reqData }
|
||||||
@@ -106,6 +112,11 @@ export const getRecentSignup = (reqData) => {
|
|||||||
return getAuxEnd(`/recent-signup`, postData)
|
return getAuxEnd(`/recent-signup`, postData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getRecentAccount = (reqData) => {
|
||||||
|
const postData = { ...reqData }
|
||||||
|
return getAuxEnd(`/recent-account`, postData)
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET PRODUCTS DATA
|
// FUNCTION TO GET PRODUCTS DATA
|
||||||
export const getProducts = (reqData) => {
|
export const getProducts = (reqData) => {
|
||||||
const postData = { ...reqData }
|
const postData = { ...reqData }
|
||||||
@@ -118,6 +129,14 @@ export const getUsers = (reqData) => {
|
|||||||
return getAuxEnd(`/users`, postData)
|
return getAuxEnd(`/users`, postData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO UPDATE USER PROFILE
|
||||||
|
export const updateUserProfile = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData
|
||||||
|
}
|
||||||
|
return postAuxEnd('/office/update-profile', postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET PRODUCTS TEMPLATE DATA
|
// FUNCTION TO GET PRODUCTS TEMPLATE DATA
|
||||||
export const getProductsTemplate = (reqData) => {
|
export const getProductsTemplate = (reqData) => {
|
||||||
const postData = { ...reqData }
|
const postData = { ...reqData }
|
||||||
|
|||||||
Reference in New Issue
Block a user