Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cfb4651af | |||
| 2d141b529c | |||
| b418ca7d58 | |||
| 9eea804f71 | |||
| f3ebb0a925 | |||
| 6421eb5b3e | |||
| 971624a358 | |||
| 21463ed501 | |||
| f450d0e868 | |||
| c880cccb5a | |||
| c776419dcf | |||
| 80d5c8ea12 | |||
| df6d2b570c | |||
| a802c1ca39 | |||
| 1a054a9fbc | |||
| 33eacecacf | |||
| a71017fae6 | |||
| 8969234fe5 | |||
| a0da97e14d | |||
| 4d1de18713 | |||
| 4fe66fd161 | |||
| 6028e4c617 | |||
| 398392062c | |||
| b84eac1299 | |||
| 52e3553aaa | |||
| 220e4952d5 | |||
| 59c90ea175 | |||
| 9838fc948e | |||
| cb4c741a90 | |||
| bba38affae | |||
| 9468793d91 | |||
| 44224e23ff | |||
| 5b926300ae | |||
| 9125730d2b | |||
| 00baa0b9bf | |||
| f5018bc6b7 | |||
| 59d9eb3df9 | |||
| 8f78011800 | |||
| 3c3f70fd3f | |||
| 4f62410e6d | |||
| b8c65ee091 | |||
| 5e1e97a2dd | |||
| f794e6d31c | |||
| a4e1376c27 | |||
| 16db88808b | |||
| 2e97ec9857 | |||
| 6ec537bebf | |||
| d84c266653 | |||
| bb5a886e47 | |||
| b5a37c4cc5 | |||
| ddde4bd0d5 | |||
| bf9c6c8b32 | |||
| 14e588b0a9 | |||
| dde01ab79a | |||
| a5f1c4b5bb | |||
| a16dd7af24 | |||
| 54d44e39d3 | |||
| 578a0e4c8f | |||
| d0ac2515a3 | |||
| b26f8b4e0d | |||
| ab6518e2ee |
@@ -1,15 +1,15 @@
|
|||||||
SKIP_PREFLIGHT_CHECK=true
|
SKIP_PREFLIGHT_CHECK=true
|
||||||
REACT_APP_NODE_ENV="development"
|
REACT_APP_NODE_ENV="development"
|
||||||
REACT_APP_SOCKET_URL="https://devsocket.mermsemr.com"
|
REACT_APP_SOCKET_URL="https://socket.mermsemr.com"
|
||||||
REACT_APP_MAIN_API="https://devapi.mermsemr.com"
|
REACT_APP_MAIN_API="https://api.mermsemr.com"
|
||||||
REACT_APP_MEDIA_SERVER="https://qa-media.mermsemr.com"
|
REACT_APP_MEDIA_SERVER="https://media.mermsemr.com"
|
||||||
REACT_APP_MAIN_SOCKET="https://devsocket.mermsemr.com"
|
REACT_APP_MAIN_SOCKET="https://dsocket.mermsemr.com"
|
||||||
|
|
||||||
# login footer links
|
# login footer links
|
||||||
REACT_APP_HOME_LINK='https://qa-www.mermsemr.com/'
|
REACT_APP_HOME_LINK='https://www.mermsemr.com/'
|
||||||
REACT_APP_ABOUT_LINK='https://qa-www.mermsemr.com/about'
|
REACT_APP_ABOUT_LINK='https://www.mermsemr.com/about'
|
||||||
REACT_APP_CONTACTS_LINK='https://qa-www.mermsemr.com/contacts'
|
REACT_APP_CONTACTS_LINK='https://www.mermsemr.com/contacts'
|
||||||
REACT_APP_TERMS_LINK='https://qa-www.mermsemr.com/terms'
|
REACT_APP_TERMS_LINK='https://www.mermsemr.com/terms'
|
||||||
|
|
||||||
# Inactivity timeout/logout AT 10MINS
|
# Inactivity timeout/logout AT 10MINS
|
||||||
REACT_APP_TIMEOUT=600000
|
REACT_APP_TIMEOUT=600000
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
.custom-bg {
|
.custom-bg {
|
||||||
background-image: url('./assets/bg/bg_1.jpg') !important;
|
background-image: url('./assets/bg/bg_2.jpg') !important;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ const queryClient = new QueryClient({
|
|||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
retry: 3,
|
retry: 3,
|
||||||
// refetchOnMount: false,
|
// refetchOnMount: false,
|
||||||
staleTime: 360000 // can also be a number in millisecond
|
staleTime: 10*60*1000 // can also be a number in millisecond
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ import ProductPage from './views/ProductPage'
|
|||||||
import SocketIOContextProvider from './component/context/SocketIOContext';
|
import SocketIOContextProvider from './component/context/SocketIOContext';
|
||||||
import CSignupPage from './views/CSignupPage';
|
import CSignupPage from './views/CSignupPage';
|
||||||
import HelpPage from './views/HelpPage';
|
import HelpPage from './views/HelpPage';
|
||||||
|
import SubscriptionPage from './views/SubscriptionPage';
|
||||||
|
import OnboardPage from "./views/OnboardPage";
|
||||||
|
import AccPWDResetPage from './views/AccPWDResetPage';
|
||||||
|
import ProfileCompletePage from './views/ProfileCompletePage';
|
||||||
|
|
||||||
|
|
||||||
function AppRouters() {
|
function AppRouters() {
|
||||||
return (
|
return (
|
||||||
@@ -32,6 +37,7 @@ function AppRouters() {
|
|||||||
<Route path={siteLinks.signup} element={<SignupPage />} />
|
<Route path={siteLinks.signup} element={<SignupPage />} />
|
||||||
<Route path={siteLinks.forgetpwd} element={<ForgetpwdPage />} />
|
<Route path={siteLinks.forgetpwd} element={<ForgetpwdPage />} />
|
||||||
<Route path={siteLinks.csignup} element={<CSignupPage />} />
|
<Route path={siteLinks.csignup} element={<CSignupPage />} />
|
||||||
|
<Route path={siteLinks.accreset} element={<AccPWDResetPage />} />
|
||||||
<Route path={siteLinks.error} element={<LoginPage />} />
|
<Route path={siteLinks.error} element={<LoginPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
@@ -39,11 +45,14 @@ function AppRouters() {
|
|||||||
<Route element={<SocketIOContextProvider />}>
|
<Route element={<SocketIOContextProvider />}>
|
||||||
<Route element={<UserExist />}>
|
<Route element={<UserExist />}>
|
||||||
<Route path={siteLinks.dash} element={<HomePage />} />
|
<Route path={siteLinks.dash} element={<HomePage />} />
|
||||||
|
<Route path={siteLinks.profile_complete} element={<ProfileCompletePage />} />
|
||||||
<Route path={siteLinks.product} element={<ProductPage />} />
|
<Route path={siteLinks.product} element={<ProductPage />} />
|
||||||
<Route path={siteLinks.reports} element={<ReportsPage />} />
|
<Route path={siteLinks.reports} element={<ReportsPage />} />
|
||||||
<Route path={siteLinks.comments} element={<CommentsPage />} />
|
<Route path={siteLinks.comments} element={<CommentsPage />} />
|
||||||
<Route path={siteLinks.contacts} element={<ContactsPage />} />
|
<Route path={siteLinks.contacts} element={<ContactsPage />} />
|
||||||
<Route path={siteLinks.user} element={<UserPage />} />
|
<Route path={siteLinks.user} element={<UserPage />} />
|
||||||
|
<Route path={siteLinks.subscription} element={<SubscriptionPage />} />
|
||||||
|
<Route path={siteLinks.onboard} element={<OnboardPage />} />
|
||||||
<Route path={siteLinks.calendar} element={<CalendarPage />} />
|
<Route path={siteLinks.calendar} element={<CalendarPage />} />
|
||||||
<Route path={siteLinks.settings} element={<SettingsPage />} />
|
<Route path={siteLinks.settings} element={<SettingsPage />} />
|
||||||
<Route path={siteLinks.help} element={<HelpPage />} />
|
<Route path={siteLinks.help} element={<HelpPage />} />
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 390 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,220 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { Form, Formik } from "formik";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
|
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||||
|
import siteLinks from '../../links/siteLinks'
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { completePWDReset, verifyResetToken } from '../../services/services';
|
||||||
|
import { updateUserDetails } from '../../store/UserDetails'
|
||||||
|
|
||||||
|
import { IoMdArrowDropdown } from "react-icons/io";
|
||||||
|
import getImage from '../../utils/getImage';
|
||||||
|
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
password: Yup.string().required("Password is required"),
|
||||||
|
confirmpassword: Yup.string().required("Confirm Password is required").oneOf([Yup.ref('password')], 'Passwords must match')
|
||||||
|
})
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
password: '',
|
||||||
|
confirmpassword: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AccPWDReset() {
|
||||||
|
|
||||||
|
const {token} = useParams()
|
||||||
|
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const [user, setUser] = useState(null)
|
||||||
|
|
||||||
|
// API to verify email link
|
||||||
|
const verifyLink = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return verifyResetToken(fields)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
// console.log('res', res.data)
|
||||||
|
if(res.data.resultCode != '0' || !res?.data?.pending_uid){
|
||||||
|
throw({message: res?.data?.resultDescription})
|
||||||
|
}
|
||||||
|
// setUser({user:'testaccount', ...res.data})
|
||||||
|
setUser(res.data)
|
||||||
|
},
|
||||||
|
// onError: (err) => {
|
||||||
|
// console.log('err', err)
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
|
||||||
|
const resetPWD = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return completePWDReset(fields)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
if(res?.data?.resultCode != '0'){
|
||||||
|
throw({message: res?.data?.resultDescription})
|
||||||
|
}
|
||||||
|
// const {token, room, uid} = res?.data
|
||||||
|
// if(!token || !room){
|
||||||
|
// throw({message: 'something went wrong, try again!'})
|
||||||
|
// }
|
||||||
|
// localStorage.setItem('token', token)
|
||||||
|
// localStorage.setItem('room', room)
|
||||||
|
// localStorage.setItem('uid', uid)
|
||||||
|
// dispatch(updateUserDetails({ ...res?.data }));
|
||||||
|
// navigate('/dash') // later add redux to dispatch state
|
||||||
|
},
|
||||||
|
// onError: (err) => {
|
||||||
|
// console.log('err', err)
|
||||||
|
// }
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleCompletePWDReset = (values) => {
|
||||||
|
let reqData = {
|
||||||
|
reset_token: token,
|
||||||
|
reset_uid: user?.pending_uid,
|
||||||
|
new_password: values.password,
|
||||||
|
}
|
||||||
|
resetPWD.mutate(reqData)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!token){
|
||||||
|
return navigate(siteLinks.login, {replace: true})
|
||||||
|
}
|
||||||
|
verifyLink.mutate({reset_token: token})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="app">
|
||||||
|
<div className="app-wrap">
|
||||||
|
<div className="app-contant">
|
||||||
|
<div className="vh-100 bg-white custom-bg">
|
||||||
|
<div className="container-fluid p-0">
|
||||||
|
<div className="row no-gutters justify-content-center">
|
||||||
|
<div className="col-11 col-sm-6 col-lg-5 col-xxl-4 align-self-center order-2 order-sm-1" style={{maxWidth: '520px'}}>
|
||||||
|
<div className="mt-5 d-flex">
|
||||||
|
<div className="bg-white register p-5">
|
||||||
|
<h1 className="mb-2">MERMS Panel</h1>
|
||||||
|
{(verifyLink.isSuccess && !resetPWD.isSuccess) && <p>Complete your password reset</p>}
|
||||||
|
<div
|
||||||
|
>
|
||||||
|
<div className='mt-2'>
|
||||||
|
<div className="row">
|
||||||
|
{resetPWD.isSuccess ?
|
||||||
|
<>
|
||||||
|
<div className='col-12'>
|
||||||
|
<div className="rounded-2 d-flex flex-column justify-content-between align-items-center" style={{backgroundColor: '#F2FAF7'}}>
|
||||||
|
<h4 className='p-4 text-black'>Your password reset is completed</h4>
|
||||||
|
<img className='' style={{width: '150px'}} src={getImage('reset-password.png')} alt='reset-icon' />
|
||||||
|
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 mt-3">
|
||||||
|
<p>Go <Link to={siteLinks.home}> Back</Link></p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
{verifyLink.isPending ?
|
||||||
|
<div className='col-12'>
|
||||||
|
<div className="rounded-2 d-flex flex-column justify-content-center align-items-center" style={{height: '200px', backgroundColor: '#F2FAF7'}}>
|
||||||
|
<div className="col-12 d-flex flex-column justify-content-center align-items-center">
|
||||||
|
<p className='text-black'>loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
: verifyLink.isSuccess ?
|
||||||
|
<div className='col-12'>
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleCompletePWDReset}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className='mt-2'>
|
||||||
|
<div className="row">
|
||||||
|
<>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-group">
|
||||||
|
<label className={`text-black fw-bold control-label`}>Username: {user?.user}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-group">
|
||||||
|
<label className={`text-black fw-bold control-label ${(props.errors.password && props.touched.password) && 'text-danger'}`}>Password*</label>
|
||||||
|
<input type="password" name='password' className="form-control" placeholder="password" value={props.values.password} onChange={props.handleChange} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="form-group">
|
||||||
|
<label className={`text-black fw-bold control-label`}>Confirm Password* <span className={`${(props.errors.confirmpassword && props.touched.confirmpassword) && 'text-danger'}`}>{(props.errors.confirmpassword && props.touched.confirmpassword) && props.errors.confirmpassword}</span></label>
|
||||||
|
<input type="password" name='confirmpassword' className="form-control" placeholder="confirmpassword" value={props.values.confirmpassword} onChange={props.handleChange} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{resetPWD.error &&
|
||||||
|
<>
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-danger'>{resetPWD.error.message}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className="col-12 mt-3 text-end">
|
||||||
|
<button type='submit' className="btn btn-primary text-uppercase">{resetPWD.isPending ? 'loading...' : 'reset password'}</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
: verifyLink.error ?
|
||||||
|
<>
|
||||||
|
<div className='col-12'>
|
||||||
|
<div className="rounded-2 d-flex flex-column justify-content-between align-items-center" style={{backgroundColor: '#E9D0DD'}}>
|
||||||
|
<h4 className='p-4 text-black'>Unable to continue password reset. Please start again</h4>
|
||||||
|
<img className='' style={{width: '150px'}} src={getImage('reset-password.png')} alt='reset-icon' />
|
||||||
|
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-12 mt-3">
|
||||||
|
<p>Go <Link to={siteLinks.home}> Back</Link></p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <div className="custom-bg col-sm-6 col-xxl-9 col-lg-7 b-gradient o-hidden order-1 order-sm-2">
|
||||||
|
<div className="row align-items-center h-100">
|
||||||
|
<div className="col-7 mx-auto ">
|
||||||
|
<img className="img-fluid" src={LoginImg} alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -87,7 +87,7 @@ export default function Calendar(){
|
|||||||
<div className="card card-statistics">
|
<div className="card card-statistics">
|
||||||
<div className="card-header">
|
<div className="card-header">
|
||||||
<div className="card-heading">
|
<div className="card-heading">
|
||||||
<h4 className="card-title">Event Calendar</h4>
|
<h4 className="card-title">Events</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ export default function Products() {
|
|||||||
:
|
:
|
||||||
<div className="row m-b-20">
|
<div className="row m-b-20">
|
||||||
{products && products.map((product, index) => (
|
{products && products.map((product, index) => (
|
||||||
<div key={product.uid+index} className="col-xxs-6 col-xl-4 col-xxl-6 mb-2 mb-xxl-0 ">
|
<div key={product.uid+index} className={`col-xxs-6 col-xl-4 col-xxl-6 mb-2 mb-xxl-0`}>
|
||||||
<Link to={productPath(product?.product_id)} >
|
<Link to={productPath(product?.product_id)} >
|
||||||
<div className="d-flex align-items-center extraProductCard">
|
<div className={`d-flex align-items-center extraProductCard ${product?.icon_style}`} >
|
||||||
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
|
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
|
||||||
<i className="fa fa-cart-plus text-primary"></i>
|
<i className={`fa ${product?.product_icon} text-primary`}></i>
|
||||||
</div>
|
</div>
|
||||||
<div className="report-details">
|
<div className="report-details">
|
||||||
<p>{product?.status_text}</p>
|
<p>{product?.status_text}</p>
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ export default function ProductsURL() {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{urlData && urlData.map((item, index) => {
|
{urlData && urlData.map((item, index) => {
|
||||||
let statusColor = item?.status === 'Preparing' ? 'badge-success-inverse' : item?.status === 'Active' ? 'badge-success-inverse' : item?.status == 'Refreshing' ? 'badge-danger-inverse' : 'badge-info-inverse'
|
let statusColor = item?.status === '1' ? 'badge-success-inverse' : item?.status === '6' ? 'badge-success-inverse' : item?.status == '7' ? 'badge-danger-inverse' : 'badge-info-inverse'
|
||||||
|
let statusText = item?.status === '1' ? 'Preparing' : item?.status === '6' ? 'Provisioning' : item?.status == '7' ? 'Ready' : 'Started'
|
||||||
let productUrl = '/product/'+ item?.product_id
|
let productUrl = '/product/'+ item?.product_id
|
||||||
let externalUrl= item?.url_protocol +"://"+ item?.internal_url;
|
let externalUrl= item?.url_protocol +"://"+ item?.internal_url;
|
||||||
return (
|
return (
|
||||||
@@ -70,7 +71,7 @@ export default function ProductsURL() {
|
|||||||
<a className="mr-3" href={externalUrl} target='_blank'><b>{externalUrl}</b></a> - {item?.description}
|
<a className="mr-3" href={externalUrl} target='_blank'><b>{externalUrl}</b></a> - {item?.description}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td><span className={`badge ${statusColor}`}>{item?.status}</span></td>
|
<td><span className={`badge ${statusColor}`}>{statusText}</span></td>
|
||||||
{/* <td><a className="mr-3" href={productUrl}><i className="fe fe-edit"></i></a></td> */}
|
{/* <td><a className="mr-3" href={productUrl}><i className="fe fe-edit"></i></a></td> */}
|
||||||
<td>
|
<td>
|
||||||
<a className="mr-3" href={productUrl}>
|
<a className="mr-3" href={productUrl}>
|
||||||
@@ -81,16 +82,6 @@ export default function ProductsURL() {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Price</th>
|
|
||||||
<th>In stock</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th>Action</th>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
</table>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export default function TopBar() {
|
|||||||
let textColor = item?.description == 'Contacts' ? 'text-danger' : item?.description == 'Site Traffic' ? 'text-primary' : item?.description == 'Appointments' ? 'text-orange' : 'text-success'
|
let textColor = item?.description == 'Contacts' ? 'text-danger' : item?.description == 'Site Traffic' ? 'text-primary' : item?.description == 'Appointments' ? 'text-orange' : 'text-success'
|
||||||
return (
|
return (
|
||||||
<div key={item.id + index} className="col-sm-6 col-xxl-3">
|
<div key={item.id + index} className="col-sm-6 col-xxl-3">
|
||||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
<div className={`card card-statistics ecommerce-contant overflow-h ${item?.extra_style} `}>
|
||||||
<div className="card-body p-0">
|
<div className="card-body p-0">
|
||||||
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
||||||
<div className="w-100">
|
<div className="w-100">
|
||||||
@@ -68,9 +68,7 @@ export default function TopBar() {
|
|||||||
<small className="d-block">{item?.data_span}</small>
|
<small className="d-block">{item?.data_span}</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="col text-right">
|
<div className="col text-right">
|
||||||
<h5 className="text-muted mb-0">{item?.description}</h5>
|
<h5 className="text-muted mb-0"><a href={item?.link}>{item?.description}</a></h5>
|
||||||
<strong className={`${textColor} m-t-5`}><i
|
|
||||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> N/A</strong>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="apexchart-wrapper">
|
<div className="apexchart-wrapper">
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import UserMenu from "./layoutcom/UserMenu";
|
import UserMenu from "./layoutcom/UserMenu";
|
||||||
import UserHeader from "./layoutcom/UserHeader";
|
import UserHeader from "./layoutcom/UserHeader";
|
||||||
import UserFooter from "./layoutcom/UserFooter";
|
import UserFooter from "./layoutcom/UserFooter";
|
||||||
import { Outlet } from 'react-router-dom';
|
import siteLinks from '../../links/siteLinks';
|
||||||
|
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
|
|
||||||
|
const {pathname} = useLocation()
|
||||||
|
// const isProfileComplete = pathname == siteLinks.profile_complete
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="app">
|
<div className="app">
|
||||||
<div className="app-wrap">
|
<div className="app-wrap">
|
||||||
<UserHeader />
|
<UserHeader />
|
||||||
<div className="app-container">
|
<div className="app-container">
|
||||||
|
|
||||||
<aside className="app-navbar">
|
<aside className="app-navbar">
|
||||||
<UserMenu />
|
<UserMenu />
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export default function UserFooter(){
|
|||||||
const year = new Date().getFullYear()
|
const year = new Date().getFullYear()
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<footer className="footer">
|
<footer className={`footer`}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-12 col-sm-6 text-center text-sm-left">
|
<div className="col-12 col-sm-6 text-center text-sm-left">
|
||||||
<p>© Copyright {year}. All rights reserved.</p>
|
<p>© Copyright {year}. All rights reserved.</p>
|
||||||
|
|||||||
@@ -73,16 +73,16 @@ export default function UserHeader(){
|
|||||||
|
|
||||||
<ul className="navbar-nav nav-right ml-auto">
|
<ul className="navbar-nav nav-right ml-auto">
|
||||||
<li className="nav-item user-profile">
|
<li className="nav-item user-profile">
|
||||||
<a onClick={toggleMenu} href="#" className="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdow">
|
<a onClick={toggleMenu} className="nav-link dropdown-toggle" role="button" data-bs-toggle="dropdow">
|
||||||
<img src={getImage('profile-pic-circle.png')} alt="avtar-img" />
|
<img src={getImage('profile-pic-circle.png')} alt="avtar-img" />
|
||||||
<span className="bg-success user-status"></span>
|
<span className="bg-success user-status"></span>
|
||||||
</a>
|
</a>
|
||||||
<div ref={nav_menu} className="dropdown-menu animated fadeIn">
|
<div ref={nav_menu} onClick={toggleMenu} className="dropdown-menu animated fadeIn">
|
||||||
<div className="bg-gradient px-4 py-3">
|
<div className="bg-gradient px-4 py-3">
|
||||||
<div className="d-flex align-items-center justify-content-between">
|
<div className="d-flex align-items-center justify-content-between">
|
||||||
<div className="mr-1">
|
<div className="mr-1">
|
||||||
<h4 className="text-white mb-0 font-600">{userDetails?.firstname} {userDetails?.lastname}</h4>
|
{/* <h4 className="text-white mb-0 font-600">{userDetails?.username}</h4> */}
|
||||||
<p className="text-white font-600">{userDetails.email}</p>
|
<p className="text-white font-600">{userDetails.username}</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" onClick={logout} className="text-white font-20 tooltip-wrapper" data-toggle="tooltip"
|
<a href="#" onClick={logout} className="text-white font-20 tooltip-wrapper" data-toggle="tooltip"
|
||||||
data-placement="top" title="" data-original-title="Logout"> <i
|
data-placement="top" title="" data-original-title="Logout"> <i
|
||||||
@@ -90,8 +90,8 @@ export default function UserHeader(){
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<Link className="dropdown-item d-flex nav-link" to={siteLinks.user}>
|
<Link className="dropdown-item d-flex nav-link" to={siteLinks.subscription}>
|
||||||
<i className="fa fa-user pr-2 text-success"></i> Users</Link>
|
<i className="fa fa-user pr-2 text-success"></i> Subscription</Link>
|
||||||
<Link className="dropdown-item d-flex nav-link" to={siteLinks.contacts}>
|
<Link className="dropdown-item d-flex nav-link" to={siteLinks.contacts}>
|
||||||
<i className="fa fa-envelope pr-2 text-primary"></i> Contacts
|
<i className="fa fa-envelope pr-2 text-primary"></i> Contacts
|
||||||
<span className="badge badge-primary ml-auto">6</span>
|
<span className="badge badge-primary ml-auto">6</span>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export default function UserMenu() {
|
|||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<ul id="collapseTwo" className="collapse" aria-labelledby="headingTwo" data-bs-parent="#sidebarNav">
|
<ul id="collapseTwo" className="collapse" aria-labelledby="headingTwo" data-bs-parent="#sidebarNav">
|
||||||
<li className={`${pathname == siteLinks.user ? 'active' : ''}`}><Link to={siteLinks.user}>Users</Link></li>
|
<li className={`${pathname == siteLinks.subscription ? 'active' : ''}`}><Link to={siteLinks.subscription}>Subscription</Link></li>
|
||||||
<li className={`${pathname == siteLinks.settings ? 'active' : ''}`}><Link to={siteLinks.settings}>Settings</Link></li>
|
<li className={`${pathname == siteLinks.settings ? 'active' : ''}`}><Link to={siteLinks.settings}>Settings</Link></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||||
|
import getImage from "../../utils/getImage";
|
||||||
|
|
||||||
|
export default function Onboard() {
|
||||||
|
|
||||||
|
const pricingFields ={
|
||||||
|
starter: { name: 'Starter', price: 5.99, active: true },
|
||||||
|
basic: { name: 'Basic', price: 12.99, active: true },
|
||||||
|
premium: { name: 'Premium', price: 20.00, active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BreadcrumbComBS title='Subscription' paths={['Dashboard', 'Subscription']} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-xl-3 col-md-6">
|
||||||
|
<div className="card card-statistics text-center py-3">
|
||||||
|
<div className="card-body pricing-content">
|
||||||
|
<div className="pricing-content-card">
|
||||||
|
<h5>Current Subscription(s)</h5>
|
||||||
|
<h2 className="text-primary pt-3">Basic</h2>
|
||||||
|
{/*<p className="text-primary pb-3">/ Monthly</p>*/}
|
||||||
|
{/*<ul className="py-2">*/}
|
||||||
|
{/* <li>post jobs</li>*/}
|
||||||
|
{/* <li>advanced instructors search</li>*/}
|
||||||
|
{/* <li>invite candidates</li>*/}
|
||||||
|
{/* <li>post events</li>*/}
|
||||||
|
{/* <li>cancel any time</li>*/}
|
||||||
|
{/*</ul>*/}
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
{Object.entries(pricingFields)?.map(([key, value]) => (
|
||||||
|
|
||||||
|
<div key={key} className="col-xl-3 col-md-6">
|
||||||
|
<div className="card card-statistics text-center py-3">
|
||||||
|
<div className="card-body pricing-content">
|
||||||
|
<div className="pricing-content-card">
|
||||||
|
<h5>{value.name}</h5>
|
||||||
|
<h2 className="text-primary pt-3">${value.price}</h2>
|
||||||
|
<p className="text-primary pb-3">/ Monthly</p>
|
||||||
|
<ul className="py-2">
|
||||||
|
<li>post jobs</li>
|
||||||
|
<li>advanced instructors search</li>
|
||||||
|
<li>invite candidates</li>
|
||||||
|
<li>post events</li>
|
||||||
|
<li>cancel any time</li>
|
||||||
|
</ul>
|
||||||
|
<div className="pt-2"><a href="javascript:void(0)" className="btn btn-inverse-secondary btn-round btn-sm">go {value.name}</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,10 +1,35 @@
|
|||||||
import React from "react";
|
import React, { useMemo, useRef, useState } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
import getImage from "../../utils/getImage";
|
import getImage from "../../utils/getImage";
|
||||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import GeneralTab from "./settingsTab/GeneralTab";
|
import { productRefreshSite, getSettingsData } from "../../services/services";
|
||||||
|
import Settings from "./settingsTab/Settings";
|
||||||
|
import queryKeys from "../../services/queryKeys";
|
||||||
|
|
||||||
|
|
||||||
export default function ProductActive(){
|
export default function ProductActive({productData}){
|
||||||
|
|
||||||
|
const iframe = useRef()
|
||||||
|
|
||||||
|
const refresh = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return productRefreshSite(fields)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
iframe.current.src += ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
const reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid'), // USER UID
|
||||||
|
product_id: productData.product_id,
|
||||||
|
subscription_uid: productData.subscription_uid
|
||||||
|
}
|
||||||
|
refresh.mutate(reqData)
|
||||||
|
}
|
||||||
|
let externalUrl= 'https://'+productData?.internal_url
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<>
|
<>
|
||||||
@@ -15,101 +40,42 @@ export default function ProductActive(){
|
|||||||
|
|
||||||
|
|
||||||
<div className="row account-contant">
|
<div className="row account-contant">
|
||||||
<>
|
<>
|
||||||
|
<div className="row tabs-contant">
|
||||||
|
<div className="col-xxl-6">
|
||||||
<div className="row tabs-contant">
|
<div className="card card-statistics">
|
||||||
<div className="col-xxl-6">
|
<div className="card-header">
|
||||||
<div className="card card-statistics">
|
<div className="card-heading d-flex justify-content-between">
|
||||||
<div className="card-header">
|
<h4 className="card-title">{externalUrl}</h4>
|
||||||
<div className="card-heading">
|
<button type="button" onClick={()=>iframe.current.src += ''} className="btn">
|
||||||
<h4 className="card-title">https://25681.devprov.mermsemr.com/</h4>
|
<img src={getImage('refresh.png')} style={{width: '30px', height: 'auto'}} alt='refresh page' />
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
</div>
|
||||||
<iframe style={{borderWidth: '0px;'}} src="https://25681.devprov.mermsemr.com/" width="100%" height="600" title="https://25681.devprov.mermsemr.com"></iframe>
|
<div className="card-body">
|
||||||
|
<iframe ref={iframe} style={{borderWidth: '0px'}} src={externalUrl} width="100%" height="600" title={externalUrl}></iframe>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="p-4 ml-auto">
|
||||||
</div>
|
<button type="button" onClick={handleRefresh} className="btn btn-primary">{refresh.isPending ? 'Loading...' : 'Refresh Site'}
|
||||||
<div className="col-xxl-6">
|
</button>
|
||||||
<div className="card card-statistics">
|
</div>
|
||||||
<div className="card-header">
|
|
||||||
<div className="card-heading">
|
|
||||||
<h4 className="card-title"> Site Settings </h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<div className="tab tab-vertical">
|
|
||||||
<ul className="nav nav-tabs" role="tablist">
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link active show" id="general-tab" data-bs-toggle="pill" data-bs-target="#general" type="button" role="tab" aria-controls="general" aria-selected="true">General</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="home-tab" data-bs-toggle="pill" data-bs-target="#home" type="button" role="tab" aria-controls="home" aria-selected="false">Home Page</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="footer-tab" data-bs-toggle="pill" data-bs-target="#footer" type="button" role="tab" aria-controls="footer" aria-selected="false">Footer</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="about-tab" data-bs-toggle="pill" data-bs-target="#about" type="button" role="tab" aria-controls="about" aria-selected="false">About Page</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="contact-tab" data-bs-toggle="pill" data-bs-target="#contact" type="button" role="tab" aria-controls="contact" aria-selected="true">Contact Page</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="social-tab" data-bs-toggle="pill" data-bs-target="#social" type="button" role="tab" aria-controls="social" aria-selected="false">Socials</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="template-tab" data-bs-toggle="pill" data-bs-target="#template" type="button" role="tab" aria-controls="template" aria-selected="false">Template</a>
|
|
||||||
</li>
|
|
||||||
<li className="nav-item">
|
|
||||||
<a className="nav-link" id="color-scheme-tab" data-bs-toggle="pill" data-bs-target="#color-scheme" type="button" role="tab" aria-controls="color-scheme" aria-selected="false">Color Scheme</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<div className="tab-content">
|
|
||||||
<div className="tab-pane fade show active" id="general" role="tabpanel" aria-labelledby="general-tab">
|
|
||||||
<GeneralTab name='General' />
|
|
||||||
</div>
|
</div>
|
||||||
<div className="tab-pane fade" id="home" role="tabpanel" aria-labelledby="home-tab">
|
</div>
|
||||||
<GeneralTab name='Home Page' />
|
<div className="col-xxl-6">
|
||||||
</div>
|
<div className="card card-statistics">
|
||||||
<div className="tab-pane fade" id="footer" role="tabpanel" aria-labelledby="footer-tab">
|
<div className="card-header">
|
||||||
<GeneralTab name='Footer' />
|
<div className="card-heading">
|
||||||
</div>
|
<h4 className="card-title"> Site Settings </h4>
|
||||||
<div className="tab-pane fade" id="about" role="tabpanel" aria-labelledby="about-tab">
|
</div>
|
||||||
<GeneralTab name='About Page' />
|
</div>
|
||||||
</div>
|
<div className="card-body">
|
||||||
<div className="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
|
<Settings productData={productData} />
|
||||||
<GeneralTab name='Contact Page' />
|
</div>
|
||||||
</div>
|
|
||||||
<div className="tab-pane fade" id="social" role="tabpanel" aria-labelledby="social-tab">
|
|
||||||
<GeneralTab name='Socials' />
|
|
||||||
</div>
|
|
||||||
<div className="tab-pane fade" id="template" role="tabpanel" aria-labelledby="template-tab">
|
|
||||||
<GeneralTab name='Template' />
|
|
||||||
</div>
|
|
||||||
<div className="tab-pane fade" id="color-scheme" role="tabpanel" aria-labelledby="color-scheme-tab">
|
|
||||||
<GeneralTab name='Color Scheme' />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1,49 +1,122 @@
|
|||||||
import React from 'react'
|
import React, {memo, useState} from 'react'
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import { pageSettings } from "../../../services/services";
|
||||||
|
import SiteTemplateSelector from './SiteTemplateSelector';
|
||||||
|
import NoYesBooleanDropdown from './NoYesBooleanDropdown';
|
||||||
|
import { IoMdArrowDropdown } from 'react-icons/io';
|
||||||
|
|
||||||
export default function GeneralTab({name='Full Name'}) {
|
const GeneralTab = memo(({name='Full Name', data, isCustom, productData, backendValues, setFieldsChanged}) =>{
|
||||||
return (
|
|
||||||
<div className="page-account-form">
|
const [reqStatus, setReqStatus] = useState({error: null, message: ''})
|
||||||
<div className="p-4">
|
|
||||||
<form>
|
const fieldData = {}
|
||||||
<h4>{name}</h4>
|
Object.entries(data)?.forEach(([key, value]) => { // LOOP TO POPULATE FIELDDATA PROPERTIES WITH DATA OF EACH TAB
|
||||||
<div className="form-row">
|
fieldData[value?.name?.toLowerCase().replaceAll(" ", "_")] = ''
|
||||||
<div className="form-group col-md-12">
|
})
|
||||||
<label htmlFor="name1">Full Name</label>
|
backendValues.forEach(item => { //LOOPING THROUGH USER ALREADY ADDED DATA FROM BACKEND IF ANY AND UPDATING THE FIELDDATA OBJECT
|
||||||
<input type="text" className="form-control" id="name1"
|
fieldData[item?.setting_key?.toLowerCase().replaceAll(" ", "_")] = item?.setting_value
|
||||||
value="Alice Williams" />
|
})
|
||||||
</div>
|
|
||||||
<div className="form-group col-md-12">
|
console.log('fieldData', fieldData)
|
||||||
<label htmlFor="title1">Title</label>
|
|
||||||
<input type="text" className="form-control" id="title1"
|
const [fields, setFields] = useState(fieldData)
|
||||||
value="Marketing expert" />
|
|
||||||
</div>
|
const handleChange = ({target:{name, value}}) => {
|
||||||
<div className="form-group col-md-12">
|
setFields(prev => ({...prev, [name]:value}))
|
||||||
<label htmlFor="phone1">Phone Number</label>
|
setFieldsChanged(true)
|
||||||
<input type="text" className="form-control" id="phone1"
|
}
|
||||||
value="(01) 97 563 15613" />
|
|
||||||
</div>
|
const submitSettings = useMutation({
|
||||||
<div className="form-group col-md-12">
|
mutationFn: (fields) => {
|
||||||
<label htmlFor="email1">Email</label>
|
return pageSettings(fields)
|
||||||
<input type="email" className="form-control" id="email1"
|
},
|
||||||
value="alicewilliams@gmail.com" />
|
onSuccess: (res) => {
|
||||||
</div>
|
if(res?.data?.resultCode != '0'){
|
||||||
</div>
|
return setReqStatus({error: true, message: 'Unable to complete, try again later'})
|
||||||
<div className="form-group">
|
}
|
||||||
<label htmlFor="add1">Address</label>
|
setFieldsChanged(false)
|
||||||
<input type="text" className="form-control" id="add1"
|
setReqStatus({error: false, message: 'Completed successfully'})
|
||||||
value="17504 Carlton Cuevas Rd, Gulfport, MS, 39503" />
|
},
|
||||||
</div>
|
onError: (err) => {
|
||||||
<div className="form-group">
|
setReqStatus({error: true, message: 'Unable to complete, try again later'})
|
||||||
<label htmlFor="add2">Address 2</label>
|
},
|
||||||
<input type="text" className="form-control" id="add2"
|
onSettled: () => {
|
||||||
value="1234 North Avenue Luke Lane, South Bend, IN 360001" />
|
setTimeout(()=>{
|
||||||
</div>
|
setReqStatus({error: null, message: ''})
|
||||||
|
},3000)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
const reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid'), // USER UID
|
||||||
|
product_id: productData?.product_id,
|
||||||
|
settings : {
|
||||||
|
...fields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log('formInfo', reqData)
|
||||||
|
submitSettings.mutate(reqData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCustom === true){
|
||||||
|
return <SiteTemplateSelector name={name} data={data} isCustom={isCustom} productData={productData} />
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
<button type="submit" className="btn btn-primary">Update Information
|
return (
|
||||||
</button>
|
<div className="page-account-form">
|
||||||
</form>
|
<div className="p-0" style={{ minHeight: '500px'}}>
|
||||||
|
|
||||||
|
<form id='tab_form'>
|
||||||
|
<div className="form-row">
|
||||||
|
<>
|
||||||
|
{Object.entries(data)?.map(([key, value]) => {
|
||||||
|
let fieldName = value.name.toLowerCase().replaceAll(" ", "_")
|
||||||
|
let fieldValue = fields[value.name.toLowerCase().replaceAll(" ", "_")]
|
||||||
|
return (
|
||||||
|
<div key={key} className="form-group col-md-12">
|
||||||
|
<label htmlFor="name1">{value.name}</label>
|
||||||
|
{value.controls == 'TEXT' ?
|
||||||
|
<input name={fieldName} type="text" className="form-control" id={key} value={fieldValue} onChange={handleChange} />
|
||||||
|
:value.controls == 'TEXTAREA' ?
|
||||||
|
<textarea name={fieldName} rows={5} style={{resize: 'none'}} type="text" className="form-control" id={key} value={fieldValue} onChange={handleChange} />
|
||||||
|
: value.controls == 'SELECT_NO_YES' ?
|
||||||
|
// <NoYesBooleanDropdown name={fieldName} value={fieldValue} onChange={handleChange} />
|
||||||
|
<div className='position-relative'>
|
||||||
|
<select onChange={handleChange} name={fieldName} value={fieldValue} className="form-control">
|
||||||
|
<option value=''>Select</option>
|
||||||
|
<option value='0'>No</option>
|
||||||
|
<option value='1'>Yes</option>
|
||||||
|
</select>
|
||||||
|
<IoMdArrowDropdown className='position-absolute w-auto' style={{top: '50%', right: '2px', transform: 'translateY(-50%)'}} />
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
{reqStatus.message &&
|
||||||
|
<>
|
||||||
|
<div className="col-12">
|
||||||
|
<p className={reqStatus.error ? 'text-danger' : 'text-success'}>{reqStatus.message}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
<div className="form-group col-md-12" style={{textAlign:'right'}}>
|
||||||
|
<button onClick={handleSubmit} type="button" className="btn btn-primary" disabled={submitSettings.isPending}>{submitSettings.isPending ? 'Loading...' : 'Update'}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
}
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
|
export default GeneralTab
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import React, {memo} from 'react'
|
||||||
|
|
||||||
|
export default function NoYesBooleanDropdown(name, value, onChange) {
|
||||||
|
return (
|
||||||
|
<select onChange={onChange} name={name} value={value} className="form-control">
|
||||||
|
<option value=''>Select</option>
|
||||||
|
<option value='0'>No</option>
|
||||||
|
<option value='1'>Yes</option>
|
||||||
|
</select>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
import React, { memo, useMemo, useState } from 'react'
|
||||||
|
import GeneralTab from './GeneralTab'
|
||||||
|
import { getSettingsData } from '../../../services/services';
|
||||||
|
import queryKeys from '../../../services/queryKeys';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
const Settings = memo(({productData}) => {
|
||||||
|
|
||||||
|
const { userDetails: { uid }} = useSelector((state) => state?.userDetails); // GETS USER UID
|
||||||
|
|
||||||
|
const dataFields ={
|
||||||
|
site_title: { name: 'Title', controls: 'TEXT', active: true },
|
||||||
|
site_description: { name: 'Description', controls: 'TEXTAREA', active: true },
|
||||||
|
site_logo_text: { name: 'Logo Text', controls: 'TEXT', active: true },
|
||||||
|
site_contact_email: { name: 'Email', controls: 'TEXT', active: true },
|
||||||
|
site_contact_phone: { name: 'Phone', controls: 'TEXT', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const socialFields ={
|
||||||
|
facebook: { name: 'Facebook', controls: 'TEXT', active: true },
|
||||||
|
twitter: { name: 'Twitter', controls: 'TEXT', active: true },
|
||||||
|
youtube: { name: 'Youtube', controls: 'TEXT', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const homeFields ={
|
||||||
|
banner_text: { name: 'Banner Text', controls: 'TEXT', active: true },
|
||||||
|
banner_description: { name: 'Banner Description', controls: 'TEXTAREA', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const footerFields ={
|
||||||
|
footer_description: { name: 'Footer Description', controls: 'TEXTAREA', active: true },
|
||||||
|
boolean_footer_show_email: { name: 'Show email in footer', controls: 'SELECT_NO_YES', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const aboutFields ={
|
||||||
|
about_title: { name: 'About Title', controls: 'TEXT', active: true },
|
||||||
|
about_description: { name: 'About Details', controls: 'TEXTAREA', active: true },
|
||||||
|
about_extra_1: { name: 'Extra About us', controls: 'TEXTAREA', active: true },
|
||||||
|
about_extra_2: { name: 'More About us', controls: 'TEXTAREA', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateData = {
|
||||||
|
template_16 : { title: 'Template Name-16', template_id: '02af24fd-2b1a-46ed-af21-87018e726408', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_22 : { title: 'Template Name-22', template_id: '8b296894-42e4-4f2e-abd1-7c2a38d6e07b', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_47 : { title: 'Template Name-47', template_id: 'ef2ffa1c-9272-42cd-9d33-0e614047b4f8', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_25 : { title: 'Template Name-25', template_id: 'b3a7ba31-dc47-4a40-a5cc-fd1ff27d6b78', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_49 : { title: 'Template Name-49', template_id: '60959c69-6672-4f69-a006-eeb7d210e605', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_27 : { title: 'Template Name-27', template_id: 'e4acb98a-c584-45f2-bece-af677dcf0a1f', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_51 : { title: 'Template Name-51', template_id: '975ee42e-3169-4978-92d7-d28e7e2ac014', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
template_9 : { title: 'Template Name-9', template_id: 'fc8f0738-6500-4775-9895-2047cd275302', banner: 'file-icon/svg.png', active: '' },
|
||||||
|
}
|
||||||
|
|
||||||
|
const contactFields ={
|
||||||
|
contact_title : { name: 'Contact Title', controls: 'TEXT', active: true },
|
||||||
|
contact_introduction: { name: 'Extra Introduction', controls: 'TEXTAREA', active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingsObject = useMemo(()=>{
|
||||||
|
return {
|
||||||
|
settings: { title: 'Settings', controls: 'settings', active: 'active show' , custom: false, data: dataFields},
|
||||||
|
home_tab: { title: 'Home Page', controls: 'home', active: '', custom: false, data: homeFields},
|
||||||
|
footer_tab: { title: 'Footer', controls: 'footer', active: '', custom: false, data: footerFields },
|
||||||
|
about_tab: { title: 'About Page', controls: 'about', active: '', custom: false, data: aboutFields },
|
||||||
|
contact_tab: { title: 'Contact Page', controls: 'contact', active: '', custom: false, data: contactFields },
|
||||||
|
social_tab: { title: 'Socials', controls: 'social', active: '', custom: false, data: socialFields },
|
||||||
|
template_tab: { title: 'Template', controls: 'template', active: '', custom: true, data: templateData },
|
||||||
|
color_scheme_tab: { title: 'Color Scheme', controls: 'color-scheme', active: '', custom: true, data: {} },
|
||||||
|
};
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
|
const [fieldsChanged, setFieldsChanged] = useState(false)
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState(Object.entries(settingsObject)[0][1]?.controls)
|
||||||
|
|
||||||
|
const handleChangeTab = (value) => {
|
||||||
|
// if(fieldsChanged){
|
||||||
|
// const proceed = confirm('Continue without saving changes')
|
||||||
|
// if(proceed){
|
||||||
|
// setActiveTab(value)
|
||||||
|
// setFieldsChanged(false)
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// setActiveTab(value)
|
||||||
|
// }
|
||||||
|
setActiveTab(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const {data, isFetching, isError, error} = useQuery({
|
||||||
|
queryKey: queryKeys.settingsData,
|
||||||
|
queryFn: () => {
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid'), // USER UID
|
||||||
|
product_id: productData?.product_id
|
||||||
|
}
|
||||||
|
return getSettingsData(reqData)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const settingsData = data?.data?.settings
|
||||||
|
// console.log('data', settingsData)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isFetching ?
|
||||||
|
<>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-mute'>Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
: isError ?
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-danger'>{error.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div className="tab tab-vertical">
|
||||||
|
<ul className="nav nav-tabs" role="tablist">
|
||||||
|
<>
|
||||||
|
{Object.entries(settingsObject).map(([key, value]) => (
|
||||||
|
<li key={key} className="nav-item">
|
||||||
|
<a className={`nav-link ${activeTab == value.controls && 'active show'}`}
|
||||||
|
id={key}
|
||||||
|
// data-bs-toggle="pill"
|
||||||
|
// data-bs-target={`#${value.controls}`}
|
||||||
|
type="button"
|
||||||
|
// role="tab"
|
||||||
|
// aria-controls={value.controls}
|
||||||
|
// aria-selected="true"
|
||||||
|
onClick={()=>handleChangeTab(value.controls)}
|
||||||
|
>
|
||||||
|
{value.title}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
</ul>
|
||||||
|
<div className="tab-content">
|
||||||
|
<>
|
||||||
|
{Object.entries(settingsObject).map(([key, value]) => (
|
||||||
|
<div key={key} className={`tab-pane fade ${activeTab == value.controls && 'active show'}`}
|
||||||
|
// id={value.controls} role="tabpanel"
|
||||||
|
// aria-labelledby={key}
|
||||||
|
>
|
||||||
|
<GeneralTab name={value.title} data={value.data} isCustom={value.custom} productData={productData} backendValues={settingsData} setFieldsChanged={setFieldsChanged} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export default Settings
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import React, {memo} from 'react'
|
||||||
|
import getImage from "../../../utils/getImage";
|
||||||
|
|
||||||
|
const SiteTemplateSelector = memo(({name='Full Name', data}) =>{
|
||||||
|
console.log("Page data == ", data)
|
||||||
|
return (
|
||||||
|
<div className="page-account-form">
|
||||||
|
<div className="p-0">
|
||||||
|
<div className="row">
|
||||||
|
<>
|
||||||
|
{Object.entries(data)?.map(([key, value]) => (
|
||||||
|
<div key={key} className="col-xl-6 col-sm-6">
|
||||||
|
<div className="card card-statistics">
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="text-center p-2">
|
||||||
|
<div className="mb-2">
|
||||||
|
<img src={getImage(value.banner)} alt={value.title} />
|
||||||
|
</div>
|
||||||
|
<h4 className="mb-0">{value.title}</h4>
|
||||||
|
<a href="javascript:void(0)" className="btn btn-light">Activate</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
export default SiteTemplateSelector
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import { Form, Formik } from "formik";
|
||||||
|
import * as Yup from "yup";
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
import getImage from "../../utils/getImage";
|
||||||
|
import { IoMdArrowDropdown } from "react-icons/io";
|
||||||
|
import { completeProfile, getCommonPractice } from '../../services/services';
|
||||||
|
|
||||||
|
|
||||||
|
const validationSchema = Yup.object().shape({
|
||||||
|
practice: Yup.string().required("Required"),
|
||||||
|
specialization: Yup.string().required("Required"),
|
||||||
|
introduction: Yup.string().min(1, "Minimum 10 characters").max(50, "Maximum 50 characters").required("Required"),
|
||||||
|
})
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
practice: '',
|
||||||
|
specialization: '',
|
||||||
|
introduction: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default function ProfileCompleteCom(){
|
||||||
|
|
||||||
|
const [practices, setPractices] = useState({practice: [], specialization: []})
|
||||||
|
|
||||||
|
const {state:{profile_completed}} = useLocation()
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return completeProfile(fields)
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
console.log('res', res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleCompleteProfile = (values, helpers) => {
|
||||||
|
// helpers.resetForm()
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid'), // USER UID
|
||||||
|
// ...values
|
||||||
|
}
|
||||||
|
console.log('values', values, helpers)
|
||||||
|
// mutation.mutate(reqData)
|
||||||
|
}
|
||||||
|
|
||||||
|
const commonPractices = useMutation({ // FUNCTION TO GET COMMON PRACTICES
|
||||||
|
mutationFn: (fields) => {
|
||||||
|
return getCommonPractice(fields)
|
||||||
|
},
|
||||||
|
onError: ()=> {
|
||||||
|
setPractices({practice: [], specialization: []})
|
||||||
|
},
|
||||||
|
onSuccess: (res) => {
|
||||||
|
let returnPractices = []
|
||||||
|
let returnSpecialization = []
|
||||||
|
setPractices(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid') // USER UID
|
||||||
|
}
|
||||||
|
commonPractices.mutate(reqData)
|
||||||
|
},[])
|
||||||
|
|
||||||
|
console.log('practices', practices)
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
<BreadcrumbComBS title='Update Profile' paths={['Dashboard', 'Profile']} />
|
||||||
|
|
||||||
|
{commonPractices?.isFetching ?
|
||||||
|
<>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-mute'>Loading...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
: commonPractices?.isError ?
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-danger'>{commonPractices?.error?.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div className="row pt-1">
|
||||||
|
<div className="col-md-6 m-b-30">
|
||||||
|
<div className="card card-statistics h-100 mb-0">
|
||||||
|
{/* <div className="card-header d-flex align-items-center justify-content-between">
|
||||||
|
<div className="card-heading">
|
||||||
|
<h4 className="card-title">My Product URLs</h4>
|
||||||
|
</div>
|
||||||
|
</div> */}
|
||||||
|
{/* <div style={{minHeight: '400px'}}></div> */}
|
||||||
|
<div className="card-body">
|
||||||
|
<Formik
|
||||||
|
initialValues={initialValues}
|
||||||
|
validationSchema={validationSchema}
|
||||||
|
onSubmit={handleCompleteProfile}
|
||||||
|
>
|
||||||
|
{(props) => {
|
||||||
|
return (
|
||||||
|
<Form className='h-100 row flex-column'>
|
||||||
|
{/* <div className="row"> */}
|
||||||
|
<>
|
||||||
|
<div className="">
|
||||||
|
<div className="form-group position-relative">
|
||||||
|
<label className={`text-black fw-bold control-label ${(props.errors.practice && props.touched.practice) && 'text-danger'}`}>Practice :</label>
|
||||||
|
<div className="position-relative">
|
||||||
|
<select onChange={props.handleChange} name='practice' value={props.values.practice} className="form-control">
|
||||||
|
<option value=''>Select</option>
|
||||||
|
<option value='engineering'>Engineering</option>
|
||||||
|
</select>
|
||||||
|
<IoMdArrowDropdown className='position-absolute w-auto' style={{top: '50%', right: '2px', transform: 'translateY(-50%)'}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="">
|
||||||
|
<div className="form-group">
|
||||||
|
<label className={`text-black fw-bold control-label ${(props.errors.specialization && props.touched.specialization) && 'text-danger'}`}>Specialization :</label>
|
||||||
|
<div className="position-relative">
|
||||||
|
<select onChange={props.handleChange} name='specialization' value={props.values.specialization} className="form-control">
|
||||||
|
<option value=''>Select</option>
|
||||||
|
<option value='construction'>Construction</option>
|
||||||
|
</select>
|
||||||
|
<IoMdArrowDropdown className='position-absolute w-auto' style={{top: '50%', right: '2px', transform: 'translateY(-50%)'}} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="">
|
||||||
|
<div className="form-group position-relative">
|
||||||
|
<label className={`text-black fw-bold control-label ${(props.errors.introduction && props.touched.introduction) && 'text-danger'}`}>General Information :</label>
|
||||||
|
<textarea name='introduction' rows={10} style={{resize: 'none'}} className="form-control" value={props.values.introduction} onChange={props.handleChange} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{/* {(mutation.isError || mutation.isSuccess) &&
|
||||||
|
<>
|
||||||
|
<div className="col-12">
|
||||||
|
<p className={`${mutation.isSuccess ? 'text-success' : 'text-danger'}`}>{mutation.isSuccess ? 'Completed successfully' : mutation.error.message}</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
} */}
|
||||||
|
|
||||||
|
<div className="mt-auto text-end">
|
||||||
|
<button type='submit' className="btn btn-primary text-uppercase">{false ? 'loading...' : 'Continue'}</button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
{/* </div> */}
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-6 m-b-30">
|
||||||
|
<div className="text-center img-block left-column wow fadeInRight">
|
||||||
|
<img className="img-fluid" src={getImage('img-07.png')} alt="content-image" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||||
|
import getImage from "../../utils/getImage";
|
||||||
|
import { getSubscriptions } from '../../services/services';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import queryKeys from '../../services/queryKeys';
|
||||||
|
|
||||||
|
export default function Subscription() {
|
||||||
|
|
||||||
|
const pricingFields ={
|
||||||
|
starter: { name: 'Starter', price: 5.99, active: true },
|
||||||
|
basic: { name: 'Basic', price: 12.99, active: true },
|
||||||
|
premium: { name: 'Premium', price: 20.00, active: true },
|
||||||
|
}
|
||||||
|
|
||||||
|
const {data, isFetching, isError, error} = useQuery({
|
||||||
|
queryKey: queryKeys.subscriptions,
|
||||||
|
queryFn: () => {
|
||||||
|
let reqData = {
|
||||||
|
token: localStorage.getItem('token'), // USER TOKEN
|
||||||
|
uid: localStorage.getItem('uid') // USER UID
|
||||||
|
}
|
||||||
|
return getSubscriptions(reqData)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentSubscription = data?.data?.current_product
|
||||||
|
const otherSubscriptions = data?.data?.options
|
||||||
|
console.log('urlData', data?.data)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BreadcrumbComBS title='Subscription' paths={['Dashboard', 'Subscription']} />
|
||||||
|
|
||||||
|
{isFetching ?
|
||||||
|
<>
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-mute'>Loading...</p>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
: isError ?
|
||||||
|
<div className="col-12">
|
||||||
|
<p className='text-danger'>{error.message}</p>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12 col-lg-6 col-xl-3">
|
||||||
|
<div className="card card-statistics text-center py-3">
|
||||||
|
<div className="card-body pricing-content">
|
||||||
|
<div className="pricing-content-card">
|
||||||
|
<h5>Current Subscription(s)</h5>
|
||||||
|
<h2 className="text-primary pt-3">{currentSubscription?.display_name}</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
{Object.entries(otherSubscriptions)?.map(([key, value]) => (
|
||||||
|
|
||||||
|
<div key={key} className="col-12 col-lg-6 col-xl-3">
|
||||||
|
<div className="card card-statistics text-center py-3">
|
||||||
|
<div className="card-body pricing-content">
|
||||||
|
<div className="pricing-content-card">
|
||||||
|
<h5>{value.display_name}</h5>
|
||||||
|
<h2 className="text-primary pt-3">${value.monthly}</h2>
|
||||||
|
<p className="text-primary pb-3">/ Monthly</p>
|
||||||
|
<ul className="py-2">
|
||||||
|
{value?.items?.map(item =>(
|
||||||
|
<li key={item}>{item}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<div className="pt-2">
|
||||||
|
<button className="btn btn-inverse-secondary btn-round btn-sm">Go {value.display_name}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
+12
-1
@@ -90,7 +90,18 @@ $today-highlight-bg: #fcf8e3;
|
|||||||
$btn-bg: #8e54e9;
|
$btn-bg: #8e54e9;
|
||||||
$btn-border: #8e54e9;
|
$btn-border: #8e54e9;
|
||||||
$event-padding: 10px;
|
$event-padding: 10px;
|
||||||
|
.manage{
|
||||||
|
background-color:lightgreen !important;
|
||||||
|
border-radius: 5px !important;
|
||||||
|
}
|
||||||
|
.creating{
|
||||||
|
background-color: lightyellow !important;
|
||||||
|
border-radius: 5px !important;
|
||||||
|
}
|
||||||
|
.billing{
|
||||||
|
background-color: darkgoldenrod;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
.extraProductCard{
|
.extraProductCard{
|
||||||
background-color: aliceblue;
|
background-color: aliceblue;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|||||||
@@ -3,17 +3,21 @@ const siteLinks = {
|
|||||||
help: '/help',
|
help: '/help',
|
||||||
home: '/',
|
home: '/',
|
||||||
dash: '/dash',
|
dash: '/dash',
|
||||||
|
profile_complete: '/profile-complete',
|
||||||
product: '/product/*',
|
product: '/product/*',
|
||||||
contacts: '/contacts',
|
contacts: '/contacts',
|
||||||
comments: '/comments',
|
comments: '/comments',
|
||||||
reports: '/reports',
|
reports: '/reports',
|
||||||
|
subscription: '/subscription',
|
||||||
|
onboard: '/subscription',
|
||||||
user: '/user',
|
user: '/user',
|
||||||
calendar: '/calendar',
|
calendar: '/calendar',
|
||||||
settings: '/settings',
|
settings: '/settings',
|
||||||
login: '/auth/login',
|
login: '/auth/login',
|
||||||
signup: '/auth/signup',
|
signup: '/auth/signup',
|
||||||
forgetpwd: '/auth/forgetpwd',
|
forgetpwd: '/auth/forgetpwd',
|
||||||
csignup: '/csignup/:jwt'
|
csignup: '/csignup/:jwt',
|
||||||
|
accreset: '/accreset/:token'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default siteLinks
|
export default siteLinks
|
||||||
@@ -5,6 +5,8 @@ const queryKeys = {
|
|||||||
myproduct_provision: ['myproduct_provision'],
|
myproduct_provision: ['myproduct_provision'],
|
||||||
product_page: ['product_page'],
|
product_page: ['product_page'],
|
||||||
recentAction: ['recent-action'],
|
recentAction: ['recent-action'],
|
||||||
|
settingsData: ['settings_data'],
|
||||||
|
subscriptions: ['subscriptions'],
|
||||||
|
|
||||||
dashboard: ['dashboard'],
|
dashboard: ['dashboard'],
|
||||||
topBar: ['top-bar'],
|
topBar: ['top-bar'],
|
||||||
|
|||||||
@@ -115,6 +115,14 @@ export const productsData = (reqData) => {
|
|||||||
return postAuxEnd(`/panel/account/products`, postData, false)
|
return postAuxEnd(`/panel/account/products`, postData, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO REFRESH SITE
|
||||||
|
export const productRefreshSite = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/account/products/refresh`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION TO GET DASHBOARD RECENT ACTIONS SECTION
|
// FUNCTION TO GET DASHBOARD RECENT ACTIONS SECTION
|
||||||
export const recentActions = (reqData) => {
|
export const recentActions = (reqData) => {
|
||||||
let postData = {
|
let postData = {
|
||||||
@@ -126,8 +134,61 @@ export const recentActions = (reqData) => {
|
|||||||
return postAuxEnd(`/panel/account/actions`, postData, false)
|
return postAuxEnd(`/panel/account/actions`, postData, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO VERIFY RESET TOKEN
|
||||||
|
export const verifyResetToken = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData
|
||||||
|
}
|
||||||
|
return postAuxEnd('/panel/auth/resetverify', postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO COMPLETE PASSWORD RESET
|
||||||
|
export const completePWDReset = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData
|
||||||
|
}
|
||||||
|
return postAuxEnd('/panel/auth/resetcomplete', postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO SUBMIT PAGE TAB SETTINGS
|
||||||
|
export const pageSettings = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/myproduct/settings`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET SETTINGS DATA
|
||||||
|
export const getSettingsData = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/myproduct/settings/values`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET PRODUCT SUBSCRIPTIONS
|
||||||
|
export const completeProfile = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/account/startprofile`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO COMPLETE PROFILE
|
||||||
|
export const getSubscriptions = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/subscription/products`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION TO GET COMMON PRACTICE
|
||||||
|
export const getCommonPractice = (reqData) => {
|
||||||
|
let postData = {
|
||||||
|
...reqData,
|
||||||
|
}
|
||||||
|
return postAuxEnd(`/panel/common/practice`, postData, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import AccPWDReset from '../component/auth/AccPWDReset'
|
||||||
|
|
||||||
|
export default function AccPWDResetPage() {
|
||||||
|
return (
|
||||||
|
<AccPWDReset />
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
import Onboard from '../component/onboard/Onboard';
|
||||||
|
|
||||||
|
|
||||||
|
export default function OnboardPage(){
|
||||||
|
return <Onboard />
|
||||||
|
}
|
||||||
@@ -1,6 +1,22 @@
|
|||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import ProductFactory from '../component/product/ProductFactory'
|
import ProductFactory from '../component/product/ProductFactory'
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import siteLinks from '../links/siteLinks';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
|
||||||
export default function ProductPage() {
|
export default function ProductPage() {
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const { userDetails: { profile_completed }} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!profile_completed){
|
||||||
|
navigate(siteLinks.profile_complete, {replace: true, state:{profile_completed: false}})
|
||||||
|
}
|
||||||
|
},[])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductFactory />
|
<ProductFactory />
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import ProfileCompleteCom from '../component/profile_complete/ProfileCompleteCom';
|
||||||
|
|
||||||
|
export default function ProfileCompletePage(){
|
||||||
|
return <ProfileCompleteCom />
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
import Subscription from '../component/subscription/Subscription';
|
||||||
|
|
||||||
|
|
||||||
|
export default function SubscriptionPage(){
|
||||||
|
return <Subscription />
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user