Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47df35d076 | |||
| 1deb15029d | |||
| 30b284064d | |||
| 4cbe78efc3 | |||
| 92ac7d74f4 | |||
| f0382cea9e | |||
| 2123af0abe | |||
| a3c306bf89 | |||
| a61abe718a | |||
| 2b91506c61 | |||
| 253cace3fe | |||
| aa55a1a4e0 | |||
| 8b763882fa | |||
| 30540e46ba | |||
| b195b1f787 | |||
| 2ddd04a1a1 | |||
| 6ea26740a4 | |||
| f334ca49f0 | |||
| fa9d7f69e4 | |||
| a4db58ba97 | |||
| ddc747d9ca | |||
| ac337eb693 | |||
| f2c3415b1d | |||
| 37450925e1 | |||
| 3b20fcec68 | |||
| d87a083c3e | |||
| 3f8a7a6b3b | |||
| 91d82db40c | |||
| 2dc12d7d0a | |||
| 164195d4cc | |||
| 7ad1a585ea | |||
| a8c2dd84f1 | |||
| ddcc6f0cd2 | |||
| 683f81e8a6 | |||
| 8e09c30c5c | |||
| af0d4db5de | |||
| 6f3dae4116 | |||
| 13900793af | |||
| 698c89edfc | |||
| 4f5a383c99 | |||
| a5b6a11880 | |||
| 0f58da3dce | |||
| 1101e80d91 | |||
| b39a7ab58c | |||
| ad90def3c9 | |||
| 737430bf04 | |||
| d371ada805 | |||
| b77f1d6213 | |||
| 64085c6be5 | |||
| 3f8b45b6d6 | |||
| 4b6c927efc | |||
| 8a8adcbbc7 | |||
| 706baadb33 | |||
| 58128fdd96 | |||
| 14e8b1b01d | |||
| 504bfbcae4 | |||
| ec47aa5f9c | |||
| 9267ded0f1 | |||
| 0b24ca650d | |||
| b535a656a0 | |||
| e69cc9130e | |||
| daafb66cbb | |||
| 3852468afe | |||
| d32204e08f | |||
| 8372209923 | |||
| 6c3f96d9a3 | |||
| c25acecb1a | |||
| 3f5ae4685e | |||
| a80298c824 | |||
| e9bc1c1318 | |||
| 2543a91b19 | |||
| 4c38b0a31f | |||
| 6ed396a34c | |||
| 465a480f02 | |||
| 4409ed45f3 | |||
| 470c94ae5e | |||
| 52fd4275e9 | |||
| 0dadaf00b0 | |||
| 0fbe0f4c3f | |||
| 464182e583 | |||
| 517886df7e |
@@ -16,3 +16,6 @@ REACT_APP_TERMS_LINK='https://qa-www.mermsemr.com/terms'
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
|
||||
# show download button
|
||||
REACT_APP_SHOW_DOWNLOAD=0
|
||||
|
||||
|
||||
@@ -17,3 +17,6 @@ REACT_APP_TERMS_LINK='https://qa-www.mermsemr.com/terms'
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
|
||||
# show download button
|
||||
REACT_APP_SHOW_DOWNLOAD=0
|
||||
|
||||
|
||||
+4
-1
@@ -14,4 +14,7 @@ REACT_APP_CONTACTS_LINK='https://www.mermsemr.com/contacts'
|
||||
REACT_APP_TERMS_LINK='https://www.mermsemr.com/terms'
|
||||
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
REACT_APP_TIMEOUT=600000
|
||||
|
||||
# show download button
|
||||
REACT_APP_SHOW_DOWNLOAD=0
|
||||
@@ -14,6 +14,10 @@
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.border-radius-10 {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.login-links{
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
|
||||
@@ -25,6 +25,7 @@ import AccPWDResetPage from './views/AccPWDResetPage';
|
||||
import ProfileCompletePage from './views/ProfileCompletePage';
|
||||
import SubscribePage from './views/Subscribe'
|
||||
import StartPage from "./views/StartPage";
|
||||
import TrafficPage from "./views/TrafficPage";
|
||||
|
||||
function AppRouters() {
|
||||
return (
|
||||
@@ -47,6 +48,7 @@ function AppRouters() {
|
||||
<Route element={<UserExist/>}>
|
||||
<Route path={siteLinks.start} element={<StartPage/>}/>
|
||||
<Route path={siteLinks.dash} element={<HomePage/>}/>
|
||||
<Route path={siteLinks.traffic} element={<TrafficPage/>}/>
|
||||
<Route path={siteLinks.profile_complete} element={<ProfileCompletePage/>}/>
|
||||
<Route path={siteLinks.product} element={<ProductPage/>}/>
|
||||
<Route path={siteLinks.reports} element={<ReportsPage/>}/>
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@@ -0,0 +1,42 @@
|
||||
import React from 'react'
|
||||
import GoogleDownload from '../../assets/img/download/andriod.jpg'
|
||||
import IOSDownload from '../../assets/img/download/apple.jpg'
|
||||
|
||||
export default function AuthFooter() {
|
||||
return (
|
||||
<div className='w-100'>
|
||||
{Number(process.env.REACT_APP_SHOW_DOWNLOAD) == 100 &&
|
||||
<>
|
||||
<div className="row" style={{margin: '5px'}}>
|
||||
<hr />
|
||||
</div>
|
||||
<div className="row" style={{marginTop: '20px'}}>
|
||||
<div className="col-6">
|
||||
<div className="app-store-icons-wrap text-center">
|
||||
<a className="icon google"
|
||||
href='#' >
|
||||
<img src={IOSDownload} className='w-80 h-auto' alt='IOS Download' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<div className="app-store-icons-wrap text-center">
|
||||
<a className="icon apple" href='#'>
|
||||
<img src={GoogleDownload} className='w-80 h-auto' alt='IOS Download' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
<div className="login-links">
|
||||
<a href={process.env.REACT_APP_HOME_LINK}>Home</a>
|
||||
<a href={process.env.REACT_APP_ABOUT_LINK}>About</a>
|
||||
<a href={process.env.REACT_APP_CONTACTS_LINK}>Contact</a>
|
||||
<a href={process.env.REACT_APP_TERMS_LINK}>Terms</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import siteLinks from '../../links/siteLinks'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { recoverPWD } from '../../services/services';
|
||||
import getImage from '../../utils/getImage';
|
||||
import AuthFooter from './AuthFooter';
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
username: Yup.string()
|
||||
@@ -17,7 +18,7 @@ const validationSchema = Yup.object().shape({
|
||||
// "Invalid email format"
|
||||
// )
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.max(25, "Maximum 25 characters")
|
||||
.required("Email is required"),
|
||||
})
|
||||
|
||||
@@ -49,7 +50,7 @@ export default function Forgetpwd2() {
|
||||
<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-1h" style={{maxWidth: '520px'}}>
|
||||
<div className="mt-5 d-flex">
|
||||
<div className="bg-white register p-5">
|
||||
<div className="bg-white register px-5 pt-5 pb-3">
|
||||
<h1 className="mb-2">{process.env.REACT_APP_PANEL_NAME}</h1>
|
||||
{!mutation.isSuccess && <p>Please enter your username.</p>}
|
||||
<Formik
|
||||
@@ -65,7 +66,7 @@ export default function Forgetpwd2() {
|
||||
<>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.username && props.touched.username) && 'text-danger'}`}>Username*</label>
|
||||
<label className={`text-black fw-bold control-label`}>Username* <span className='text-danger' style={{fontSize: '12px'}}>{(props.errors.username && props.touched.username) && props.errors.username}</span></label>
|
||||
<input type="text" name='username' className="form-control" placeholder="Username" value={props.values.username} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -97,6 +98,7 @@ export default function Forgetpwd2() {
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
<AuthFooter />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,7 @@ import siteLinks from '../../links/siteLinks'
|
||||
import { loginUser } from '../../services/services'
|
||||
import { updateUserDetails } from '../../store/UserDetails'
|
||||
|
||||
import GoogleDownload from '../../assets/img/download/andriod.jpg'
|
||||
import IOSDownload from '../../assets/img/download/apple.jpg'
|
||||
import AuthFooter from './AuthFooter'
|
||||
|
||||
export default function Login() {
|
||||
|
||||
@@ -47,12 +46,12 @@ export default function Login() {
|
||||
console.log(error)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if(res?.data?.error_message){
|
||||
if(res?.data && res?.data?.error_message){
|
||||
throw({message: res?.data?.error_message})
|
||||
}
|
||||
const {token, room, uid} = res?.data
|
||||
if(!token || !room){
|
||||
throw({message: 'something went wrong, try again!'})
|
||||
throw({message: 'Unable to complete your login, Please try again!'})
|
||||
}
|
||||
localStorage.setItem('token', token)
|
||||
localStorage.setItem('room', room)
|
||||
@@ -93,13 +92,13 @@ export default function Login() {
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className="control-label text-black fw-bold">User Name*</label>
|
||||
<input maxLength={55} name='username' value={fields.username} onChange={handleChange} type="text" className="form-control" placeholder="Username" />
|
||||
<input maxLength={25} name='username' value={fields.username} onChange={handleChange} type="text" className="form-control" placeholder="Username" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className="control-label text-black fw-bold">Password*</label>
|
||||
<input maxLength={55} name='password' value={fields.password} onChange={handleChange} type="password" className="form-control" placeholder="Password" />
|
||||
<input maxLength={25} name='password' value={fields.password} onChange={handleChange} type="password" className="form-control" placeholder="Password" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
@@ -133,35 +132,7 @@ export default function Login() {
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div className="row" style={{margin: '5px'}}>
|
||||
<hr />
|
||||
</div>
|
||||
<div className="row" style={{marginTop: '20px'}}>
|
||||
<div className="col-6">
|
||||
<div className="app-store-icons-wrap text-center">
|
||||
<a className="icon google"
|
||||
href='#' >
|
||||
<img src={IOSDownload} className='w-80 h-auto' alt='IOS Download' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<div className="app-store-icons-wrap text-center">
|
||||
<a className="icon apple" href='#'>
|
||||
<img src={GoogleDownload} className='w-80 h-auto' alt='IOS Download' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="login-links">
|
||||
<a href={process.env.REACT_APP_HOME_LINK}>Home</a>
|
||||
<a href={process.env.REACT_APP_ABOUT_LINK}>About</a>
|
||||
<a href={process.env.REACT_APP_CONTACTS_LINK}>Contact</a>
|
||||
<a href={process.env.REACT_APP_TERMS_LINK}>Terms</a>
|
||||
</div>
|
||||
|
||||
<AuthFooter />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -82,9 +82,13 @@ export default function Signup() {
|
||||
</button>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<hr />
|
||||
<p className='font-medium'>Already have an account ?
|
||||
<Link to={siteLinks.login}
|
||||
className='hover:text-primary font-bold'> Sign In
|
||||
className='bg-secondary; hover:text-primary font-bold' style={{paddingRight: '10px'}}>
|
||||
<button className="btn btn-warning text-uppercase">
|
||||
Sign In
|
||||
</button>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
+155
-111
@@ -1,101 +1,120 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Form, Formik } from "formik";
|
||||
import React, {useState} from 'react'
|
||||
import {Form, Formik} from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
// import LoginImg from '../../assets/bg/login.svg'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
import {Link} from 'react-router-dom'
|
||||
import siteLinks from '../../links/siteLinks'
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { signUpUser } from '../../services/services';
|
||||
import {useMutation} from '@tanstack/react-query';
|
||||
import {signUpUser} from '../../services/services';
|
||||
import getImage from '../../utils/getImage';
|
||||
import AuthFooter from './AuthFooter';
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
email: Yup.string()
|
||||
.email("Wrong email format")
|
||||
// .matches(
|
||||
// /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
||||
// "Invalid email format"
|
||||
// )
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Email is required"),
|
||||
.email("Wrong email format")
|
||||
// .matches(
|
||||
// /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/,
|
||||
// "Invalid email format"
|
||||
// )
|
||||
.min(3, "Minimum 3 characters")
|
||||
.max(50, "Maximum 50 characters")
|
||||
.required("Email is required"),
|
||||
firstname: Yup.string().required("Firstname is required"),
|
||||
lastname: Yup.string().required("Lastname is required"),
|
||||
isChecked: Yup.bool().oneOf([true], "Please accept the terms & policy"), // use bool instead of boolean
|
||||
// username: Yup.string().min(3, "Minimum 3 characters").max(50, "Maximum 50 characters").required("Email is required"),
|
||||
// password: Yup.string().min(3, "Minimum 3 characters").max(50, "Maximum 50 characters").required("Email is required"),
|
||||
})
|
||||
})
|
||||
|
||||
const initialValues = {
|
||||
const initialValues = {
|
||||
email: '',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
isChecked: false,
|
||||
// username: '',
|
||||
// password: ''
|
||||
};
|
||||
};
|
||||
|
||||
export default function Signup2() {
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return signUpUser(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
console.log('res', res)
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return signUpUser(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
console.log('res', res)
|
||||
}
|
||||
})
|
||||
|
||||
const signUp = (values) => {
|
||||
// helpers.resetForm()
|
||||
// console.log('values', values, helpers)
|
||||
delete values.isChecked
|
||||
mutation.mutate(values)
|
||||
}
|
||||
})
|
||||
|
||||
const signUp = (values) => {
|
||||
// helpers.resetForm()
|
||||
// console.log('values', values, helpers)
|
||||
delete values.isChecked
|
||||
mutation.mutate(values)
|
||||
}
|
||||
|
||||
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">{process.env.REACT_APP_PANEL_NAME}</h1>
|
||||
<p>Welcome, Please create your account.</p>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={signUp}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='mt-2 mt-sm-5'>
|
||||
<div className="row">
|
||||
{!mutation.isSuccess ?
|
||||
<>
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.firstname && props.touched.firstname) && 'text-danger'}`}>First Name*</label>
|
||||
<input type="text" name='firstname' className="form-control" placeholder="First Name" value={props.values.firstname} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.lastname && props.touched.lastname) && 'text-danger'}`}>Last Name*</label>
|
||||
<input type="text" name='lastname' className="form-control" placeholder="Last Name" value={props.values.lastname} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.email && props.touched.email) && 'text-danger'}`}>Email*</label>
|
||||
<input type="email" name='email' className="form-control" placeholder="Email" value={props.values.email} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="col-12">
|
||||
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 px-5 pt-5 pb-3">
|
||||
<h1 className="mb-2">{process.env.REACT_APP_PANEL_NAME}</h1>
|
||||
<p>Welcome, please create your account.</p>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={signUp}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='mt-2 mt-sm-5'>
|
||||
<div className="row">
|
||||
{!mutation.isSuccess ?
|
||||
<>
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="form-group">
|
||||
<label
|
||||
className={`text-black fw-bold control-label ${(props.errors.firstname && props.touched.firstname) && 'text-danger'}`}>First
|
||||
Name*</label>
|
||||
<input type="text" name='firstname'
|
||||
className="form-control"
|
||||
placeholder="First Name"
|
||||
value={props.values.firstname}
|
||||
onChange={props.handleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-6">
|
||||
<div className="form-group">
|
||||
<label
|
||||
className={`text-black fw-bold control-label ${(props.errors.lastname && props.touched.lastname) && 'text-danger'}`}>Last
|
||||
Name*</label>
|
||||
<input type="text" name='lastname'
|
||||
className="form-control"
|
||||
placeholder="Last Name"
|
||||
value={props.values.lastname}
|
||||
onChange={props.handleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
className={`text-black fw-bold control-label ${(props.errors.email && props.touched.email) && 'text-danger'}`}>Email*</label>
|
||||
<input type="email" name='email'
|
||||
className="form-control"
|
||||
placeholder="Email"
|
||||
value={props.values.email}
|
||||
onChange={props.handleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.username && props.touched.username) && 'text-danger'}`}>Username*</label>
|
||||
<input type="text" name='username' className="form-control" placeholder="Username" value={props.values.username} onChange={props.handleChange} />
|
||||
@@ -107,62 +126,87 @@ export default function Signup2() {
|
||||
<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-check">
|
||||
<input name='isChecked' className="form-check-input" type="checkbox" id="gridCheck" value={props.values.isChecked} onChange={props.handleChange} />
|
||||
<label className="form-check-label" htmlFor="gridCheck">
|
||||
I accept terms & policy
|
||||
</label>
|
||||
</div>
|
||||
<span className={`${(props.errors.isChecked && props.touched.isChecked) && 'text-danger'}`}>{props.errors.isChecked}</span>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-check">
|
||||
<input name='isChecked'
|
||||
className="form-check-input"
|
||||
type="checkbox" id="gridCheck"
|
||||
value={props.values.isChecked}
|
||||
onChange={props.handleChange}/>
|
||||
<label className="form-check-label"
|
||||
htmlFor="gridCheck">
|
||||
I accept terms & policy
|
||||
</label>
|
||||
</div>
|
||||
<span
|
||||
className={`${(props.errors.isChecked && props.touched.isChecked) && 'text-danger'}`}>{props.errors.isChecked}</span>
|
||||
</div>
|
||||
|
||||
{mutation.error &&
|
||||
<>
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{mutation.error.message}</p>
|
||||
</div>
|
||||
{mutation.error &&
|
||||
<>
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{mutation.error.message}</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3 text-end">
|
||||
<button type='submit'
|
||||
className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Sign up'}</button>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<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'
|
||||
style={{marginBottom: '-30px'}}>Check
|
||||
your email to continue.</h4>
|
||||
<img className='' style={{width: '200px'}}
|
||||
src={getImage('check-mail.png')}
|
||||
alt='mail-alert'/>
|
||||
<Link to={siteLinks.login}
|
||||
className='p-2 text-primary'
|
||||
style={{color: '#6FCAEF'}}>Home</Link>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3 text-end">
|
||||
<button type='submit' className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Sign up'}</button>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<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' style={{marginBottom: '-30px'}}>Check your email to continue.</h4>
|
||||
<img className='' style={{width: '200px'}} src={getImage('check-mail.png')} alt='mail-alert' />
|
||||
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||
<div className="col-12 mt-3">
|
||||
<p>
|
||||
<span style={{paddingLeft: '5px' , fontWeight: 'bolder'}}>Already have an account? </span>
|
||||
<Link
|
||||
to={siteLinks.login}>
|
||||
<button
|
||||
className="btn btn-warning text-uppercase">
|
||||
Sign In
|
||||
</button>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3">
|
||||
<p>Already have an account ?<Link to={siteLinks.login}> Sign In</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
<AuthFooter />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="signup-bg col-sm-6 col-xxl-9 col-lg-7 b-gradient o-hidden order-1 order-sm-2">
|
||||
{/* <div className="signup-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>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ export default function Calendar(){
|
||||
}
|
||||
const {data, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.calendar_events,
|
||||
queryFn: () => getCalendarEvents(reqData)
|
||||
queryFn: () => getCalendarEvents(reqData),
|
||||
staleTime: 0
|
||||
})
|
||||
|
||||
const receievedEvents = data?.data
|
||||
|
||||
+323
-532
@@ -1,558 +1,349 @@
|
||||
import React from "react";
|
||||
"use client";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
import getImage from "../../utils/getImage";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { commentsData } from "../../services/services";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
import getCustomTime from "../../utils/getCustomTime";
|
||||
|
||||
export default function Comments() {
|
||||
// const {data:contacts, isFetching, isError, error} = useQuery({
|
||||
// queryKey: queryKeys.contacts,
|
||||
// queryFn: () => contactData()
|
||||
// })
|
||||
|
||||
const [activeCategoryUID, setActiveCategoryUID] = useState("0"); // HOLDS VALUE OF THE ACTIVE CATEGORY
|
||||
|
||||
const [activeContactUID, setActiveContactUID] = useState("");
|
||||
const [activeDetail, setActiveDetail] = useState([]);
|
||||
|
||||
const [filteredContactData, setFiltererdContactData] = useState([]);
|
||||
|
||||
const getContactData = useMutation({
|
||||
mutationFn: (reqData) => {
|
||||
return commentsData(reqData);
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error);
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if (res?.data?.resultCode != "0") {
|
||||
throw { message: "Something went wrong" };
|
||||
}
|
||||
setFiltererdContactData(res?.data?.contacts);
|
||||
},
|
||||
});
|
||||
|
||||
const changeActiveUID = (uid) => {
|
||||
setActiveContactUID(uid);
|
||||
let detail = contactsData.filter((item) => item.uid == uid);
|
||||
setActiveDetail(detail);
|
||||
};
|
||||
|
||||
const changeActiveCategoryUID = (id) => {
|
||||
let filteredConData = [];
|
||||
setActiveCategoryUID(id);
|
||||
if (id == "0") {
|
||||
filteredConData = contactsData;
|
||||
} else {
|
||||
filteredConData = contactsData.filter((item) => item.category == id);
|
||||
}
|
||||
setFiltererdContactData(filteredConData);
|
||||
changeActiveUID(filteredConData[0]?.uid);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem("token"), // USER TOKEN
|
||||
uid: localStorage.getItem("uid"), // USER UID
|
||||
};
|
||||
getContactData.mutate(reqData);
|
||||
}, []);
|
||||
|
||||
const contactsData = getContactData?.data?.data?.contacts; // LIST OF CONTACTS
|
||||
const contactsCategory = getContactData?.data?.data?.category; // LIST OF CATEGORY
|
||||
|
||||
return (
|
||||
<>
|
||||
<BreadcrumbComBS title="Comments" paths={["Dashboard", "Comments"]} />
|
||||
<div className="row">
|
||||
{/*<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>*/}
|
||||
<div className="col-12">
|
||||
<div className="card card-statistics mail-contant">
|
||||
<div className="card-body p-0">
|
||||
<div className="row no-gutters">
|
||||
<div className="col-md-4 col-xxl-2 col-md-4">
|
||||
<div className="mail-sidebar">
|
||||
<div className="row justify-content-center">
|
||||
<div className="col-12">
|
||||
<div className="text-center mail-sidebar-title px-4">
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
className="btn btn-primary btn-block py-3 font-weight-bold font-18"
|
||||
>
|
||||
<i className="fa fa-plus pl-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="px-4 py-4">
|
||||
<ul className="pl-0">
|
||||
<li className="py-2">
|
||||
<a href="javascript:void(0)">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-envelope-o text-primary pr-4"></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>Inbox</span>
|
||||
</span>
|
||||
<span className="nav-item ml-auto text-right">
|
||||
<span className="badge badge-pill badge-primary float-right">
|
||||
0+
|
||||
<>
|
||||
<BreadcrumbComBS title="Comments" paths={["Dashboard", "Comments"]} />
|
||||
{getContactData?.isPending ? (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className="text-mute">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : getContactData?.error ? (
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className="text-danger">{getContactData?.error?.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="row">
|
||||
{/*<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>*/}
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="card card-statistics mail-contant"
|
||||
style={{ minHeight: "200px", borderRadius: "10px" }}
|
||||
>
|
||||
<div className="card-body p-0">
|
||||
<div className="row no-gutters">
|
||||
<div className="col-md-4 col-xxl-2 col-md-4">
|
||||
<div className="mail-sidebar">
|
||||
<div className="row justify-content-center">
|
||||
<div className="d-none col-12">
|
||||
<div className="text-center mail-sidebar-title px-4">
|
||||
<a
|
||||
href="#"
|
||||
className="btn btn-primary btn-block py-3 font-weight-bold font-18"
|
||||
>
|
||||
<i className="fa fa-plus pl-2"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="px-4 py-4">
|
||||
<ul className="pl-0">
|
||||
<li className="py-2">
|
||||
<a href="#">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-envelope-o text-primary pr-4"></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>Inbox</span>
|
||||
</span>
|
||||
<span className="nav-item ml-auto text-right">
|
||||
<span className="badge badge-pill badge-primary float-right">
|
||||
{contactsData?.length}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="py-2">
|
||||
<a href="javascript:void(0)">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-paper-plane-o pr-4"></i>
|
||||
</a>
|
||||
</li>
|
||||
{/*<li className="py-2">*/}
|
||||
{/* <a href="#">*/}
|
||||
{/* <span*/}
|
||||
{/* className="nav align-items-center">*/}
|
||||
{/* <span>*/}
|
||||
{/* <i className="fa fa-paper-plane-o pr-4"></i>*/}
|
||||
{/* </span>*/}
|
||||
{/* <span>*/}
|
||||
{/* <span>Replied Mail</span>*/}
|
||||
{/* </span>*/}
|
||||
{/* </span>*/}
|
||||
{/* </a>*/}
|
||||
{/*</li>*/}
|
||||
</ul>
|
||||
|
||||
<ul className="pl-0 mt-5">
|
||||
<li
|
||||
className="py-2"
|
||||
onClick={() => changeActiveCategoryUID("0")}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<div>
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i
|
||||
className={`fa fa-circle-o pr-4 ${
|
||||
activeCategoryUID == "0"
|
||||
? "text-primary"
|
||||
: "text-warning"
|
||||
}`}
|
||||
></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>All</span>
|
||||
</span>
|
||||
</span>
|
||||
<span>
|
||||
<span>Sent Mail</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="pl-0 mt-5">
|
||||
<li className="py-2">
|
||||
<a href="javascript:void(0)">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-circle-o text-danger pr-4"></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>Personal</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="py-2">
|
||||
<a href="javascript:void(0)">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-circle-o pr-4 text-warning"></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>Work</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li className="py-2">
|
||||
<a href="javascript:void(0)">
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i className="fa fa-plus pr-4"></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>Add Category</span>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-8 col-xxl-4 border-md-t">
|
||||
<div className="mail-content border-right border-n h-100">
|
||||
<div className="mail-search border-bottom">
|
||||
<div className="row align-items-center mx-0">
|
||||
<div className="col-12">
|
||||
<div className="form-group pt-3">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="search"
|
||||
placeholder="Search.."
|
||||
/>
|
||||
<i className="fa fa-search"></i>
|
||||
</div>
|
||||
</li>
|
||||
{contactsCategory &&
|
||||
contactsCategory.map((item) => (
|
||||
<li
|
||||
key={item?.cid}
|
||||
className="py-2"
|
||||
onClick={() =>
|
||||
changeActiveCategoryUID(`${item?.cid}`)
|
||||
}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<div>
|
||||
<span className="nav align-items-center">
|
||||
<span>
|
||||
<i
|
||||
className={`fa fa-circle-o pr-4 ${
|
||||
activeCategoryUID ==
|
||||
`${item?.cid}`
|
||||
? "text-primary"
|
||||
: "text-warning"
|
||||
}`}
|
||||
></i>
|
||||
</span>
|
||||
<span>
|
||||
<span>{item?.description}</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mail-msg scrollbar scroll_dark">
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/01.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Martin smith</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">Saas Designer</h5>
|
||||
<p>
|
||||
Since there is not an "all the above" category,
|
||||
I'll take the opportunity to enthusiastically
|
||||
congratulate you on the very high quality.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
<div className={`${filteredContactData.length > 0 ? 'col-md-8 col-xxl-4' : 'col-md-8 col-xxl-10'} border-md-t`}>
|
||||
<div className="mail-content border-right border-n h-100" style={{placeContent: 'center'}}>
|
||||
{/* <div className="mail-search border-bottom">
|
||||
<div className="row align-items-center mx-0">
|
||||
<div className="col-12">
|
||||
<div className="form-group pt-3">
|
||||
<input type="text" className="form-control" id="search" placeholder="Search.." />
|
||||
<i className="fa fa-search"></i>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="mail-msg scrollbar scroll_dark">
|
||||
{ filteredContactData.length ?
|
||||
filteredContactData?.map((contact, index) => {
|
||||
const isActive =
|
||||
contact?.uid == activeContactUID ||
|
||||
(!activeContactUID && index == 0);
|
||||
const avtarImage =
|
||||
contact?.category === undefined
|
||||
? "avtar/01.jpg"
|
||||
: "avtar/" + contact.category + ".png";
|
||||
return (
|
||||
<div
|
||||
key={contact?.uid}
|
||||
onClick={() => changeActiveUID(contact?.uid)}
|
||||
className={`mail-msg-item ${
|
||||
isActive && "bg-light"
|
||||
}`}
|
||||
>
|
||||
<a href="#">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage(avtarImage)}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>
|
||||
<span
|
||||
style={{
|
||||
fontSize: "14px",
|
||||
color: "#148399",
|
||||
fontWeight: "bolder",
|
||||
}}
|
||||
>
|
||||
{contact?.sender}
|
||||
</span>
|
||||
</p>
|
||||
{/* <p className="d-none d-xl-block">06:59 <span> PM </span></p> */}
|
||||
<p className="d-none d-xl-block">
|
||||
<span style={{ fontSize: "14px" }}>
|
||||
{new Date(
|
||||
contact?.added
|
||||
).toDateString()}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">
|
||||
{contact?.title}
|
||||
</h5>
|
||||
<p>
|
||||
{contact?.message?.length < 100
|
||||
? contact?.message
|
||||
: contact?.message.substring(0, 101) +
|
||||
" ..."}
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
<span>
|
||||
{new Date(
|
||||
contact?.added
|
||||
).toDateString()}
|
||||
{/* {getCustomTime(contact.added)} */}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
:
|
||||
<p className="text-center">Messages will appear here as soon as they are available for selection</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/02.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
{filteredContactData.length > 0 &&
|
||||
<div className="col-xxl-6 border-t border-xxl-t">
|
||||
<div className="mail-chat py-5 px-5">
|
||||
<div className="media align-items-center">
|
||||
<div className="bg-img mr-3">
|
||||
<img
|
||||
src={activeContactUID ? getImage("avtar/" + activeDetail[0].category + ".png") : getImage(filteredContactData[0] == undefined ? "avtar/01.jpg": "avtar/" + filteredContactData[0].category + ".png")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mb-0" style={{ color: "#148399" }}>
|
||||
{activeContactUID
|
||||
? activeDetail[0]?.sender
|
||||
: filteredContactData[0]?.sender}
|
||||
</h4>
|
||||
<p>
|
||||
{activeContactUID
|
||||
? new Date(activeDetail[0]?.added).toDateString()
|
||||
: new Date(
|
||||
filteredContactData[0]?.added
|
||||
).toDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>DutcaPatrick</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
<div className="mt-4 d-flex justify-content-between">
|
||||
<div>
|
||||
<h3>
|
||||
{activeContactUID
|
||||
? activeDetail[0]?.title
|
||||
: filteredContactData[0]?.title}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{/*<a href="javascript:void(0)"><i className="fa fa-reply font-22 pr-3"></i></a>*/}
|
||||
{/*<a href="javascript:void(0)"><i className="fa fa-print font-22"></i></a>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
{activeContactUID
|
||||
? activeDetail[0]?.message
|
||||
: filteredContactData[0]?.message}
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">
|
||||
Mobile app Designer{" "}
|
||||
</h5>
|
||||
<p>
|
||||
Very nice template, lots of pages and good
|
||||
documentation.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/03.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>m_morsch</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">
|
||||
Landing page Designer
|
||||
</h5>
|
||||
<p>
|
||||
Excellent and at a great price... thank you very
|
||||
much!
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/04.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>AnnaHorno</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">Re-Design ios app</h5>
|
||||
<p>
|
||||
Solved my theme problem in 10 minutes. We thank
|
||||
you.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/05.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Wdcorbitt</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">
|
||||
Mobil UX/UI Designer
|
||||
</h5>
|
||||
<p>
|
||||
Asked for information and received it EXTREMELY
|
||||
quickly. Great layout - good code - great price!{" "}
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/06.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Anne Smith</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">Jobly Opportunity</h5>
|
||||
<p>
|
||||
Mentor has so many features and layouts. Its a
|
||||
great choice.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/07.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Paul Flavius</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">Saas Designer</h5>
|
||||
<p>
|
||||
There are many people in the world with amazing
|
||||
talents who realize only a small percentage of
|
||||
their potential.{" "}
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/08.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Sara Lisbon</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">UI Designer</h5>
|
||||
<p>
|
||||
We can look a bit further back in time to Albert
|
||||
Einstein or even further back to Abraham
|
||||
Lincoln.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="mail-msg-item">
|
||||
<a href="javascript:void(0)">
|
||||
<div className="media align-items-center">
|
||||
<div className="mr-3">
|
||||
<div className="bg-img">
|
||||
<img
|
||||
src={getImage("avtar/09.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="mail-msg-item-titel justify-content-between">
|
||||
<p>Annahorno</p>
|
||||
<p className="d-none d-xl-block">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
<h5 className="mb-0 my-2">Saas Designer</h5>
|
||||
<p>
|
||||
One of the most difficult aspects of achieving
|
||||
success is staying motivated over the long haul.
|
||||
</p>
|
||||
<p className="d-xl-none">
|
||||
06:59 <span> PM </span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xxl-6 border-t border-xxl-t">
|
||||
<div className="mail-chat py-5 px-5">
|
||||
<div className="media align-items-center">
|
||||
<div className="bg-img mr-3">
|
||||
<img
|
||||
src={getImage("avtar/03.jpg")}
|
||||
className="img-fluid"
|
||||
alt="user"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mb-0">Dutca Patrick</h4>
|
||||
<p>30 Min ago</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 d-flex justify-content-between">
|
||||
<div>
|
||||
<h3>Landing page Designer...</h3>
|
||||
</div>
|
||||
<div className="d-flex">
|
||||
{/*<a href="javascript:void(0)"><i className="fa fa-reply font-22 pr-3"></i></a>*/}
|
||||
{/*<a href="javascript:void(0)"><i className="fa fa-print font-22"></i></a>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="my-4">hey adminjon...</p>
|
||||
<p className="mb-2">
|
||||
I truly believe Augustine’s words are true and if you
|
||||
look at history you know it is true. There are many
|
||||
people in the world with amazing talents who realize
|
||||
only a small percentage of their potential. We all know
|
||||
people who live this truth.
|
||||
</p>
|
||||
<p>
|
||||
We also know those epic stories, those modern-day
|
||||
legends surrounding the early failures of such supremely
|
||||
successful folks as Michael Jordan and Bill Gates. We
|
||||
can look a bit further back in time to Albert Einstein
|
||||
or even further back to Abraham Lincoln. What made each
|
||||
of these people so successful? Motivation.
|
||||
</p>
|
||||
<p>
|
||||
We know this in our gut, but what can we do about it?
|
||||
How can we motivate ourselves? One of the most difficult
|
||||
aspects of achieving success is staying motivated over
|
||||
the long haul.
|
||||
</p>
|
||||
<div className="my-5">
|
||||
<p>Have lovely Day,</p>
|
||||
<p>adminjon</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/*<div className="d-md-flex px-5 py-4">*/}
|
||||
{/* <div className="flex-fill align-items-center">*/}
|
||||
{/* <div className="d-flex">*/}
|
||||
{/* <i className="ti ti-clip pr-3 font-22"></i>*/}
|
||||
{/* <p className="pr-3 font-weight-bold">Wireframe</p>*/}
|
||||
{/* <p>(220.MB)</p>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="flex-fill text-left text-md-right"><a href="javascript:void(0)" className="text-primary"><i className="ti ti-download pr-2"></i><span>Download</span></a></div>*/}
|
||||
{/*</div>*/}
|
||||
<div className="bg-light mail-f px-4 py-3">
|
||||
<div className="py-2 bg-white px-4 py-3 d-flex justify-content-between">
|
||||
<p>
|
||||
Click here to{" "}
|
||||
<a
|
||||
href="#editer"
|
||||
data-toggle="collapse"
|
||||
className="text-primary px-1"
|
||||
>
|
||||
Reply
|
||||
</a>
|
||||
or
|
||||
<a
|
||||
href="#forward"
|
||||
data-toggle="collapse"
|
||||
className="text-primary px-1"
|
||||
>
|
||||
Forward
|
||||
</a>
|
||||
</p>
|
||||
<a href="javascript:void(0)" className="text-primary">
|
||||
<i className="fa fa-microphone"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div className="collapse" id="editer">
|
||||
<div className="form-group">
|
||||
<textarea
|
||||
className="form-control mt-3"
|
||||
id="exampleFormControlTextarea1"
|
||||
rows="3"
|
||||
placeholder="Type here..."
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div className="collapse" id="forward">
|
||||
<div className="form-group">
|
||||
<input
|
||||
className="form-control mt-3"
|
||||
id="exampleFormControl"
|
||||
placeholder="Email Address"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex align-items-center justify-content-between py-2">
|
||||
<div>
|
||||
<ul className="nav">
|
||||
<li className="nav-item pr-3">
|
||||
<a href="javascript:void(0)">
|
||||
<i className="ti ti-clip font-20"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item pr-3">
|
||||
<a href="javascript:void(0)">
|
||||
<i className="ti ti-face-smile font-20"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a href="javascript:void(0)">
|
||||
<i className="ti ti-gallery font-20"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
className="btn btn-primary"
|
||||
>
|
||||
<span>Send</span>{" "}
|
||||
<i className="fa fa-paper-plane"></i>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export default function SocketIOContextProvider({children}) {
|
||||
socket.on(socketOnEvents.receive_message, (data) => {
|
||||
// setSocketMsgReceived(data.message);
|
||||
// dispatch(tableReload({type:'CHATMESSAGELIST'})) // dispatches to update chat message sending from owner to worker and vice versa
|
||||
console.log('DATA', data)
|
||||
console.log('SOCKET RECEIVED DATA *** ', data)
|
||||
queryClient.refetchQueries({
|
||||
queryKey: [...queryKeys.recentAction],
|
||||
// type: 'active',
|
||||
|
||||
@@ -54,12 +54,12 @@ export default function DashPayments() {
|
||||
{/* <th style={{width: '30px'}}>#</th> */}
|
||||
<th>Date</th>
|
||||
|
||||
<th style={{width: '130px'}}>Subscription</th>
|
||||
<th style={{width: '130px'}}>Description</th>
|
||||
<th style={{width: '80px'}}>Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{payments.length > 0 ?
|
||||
{payments && payments?.length > 0 ?
|
||||
payments.map((item, index) => {
|
||||
return (
|
||||
<tr key={index}>
|
||||
|
||||
@@ -50,7 +50,7 @@ export default function Products() {
|
||||
</div>
|
||||
<div className="report-details">
|
||||
<p><span style={{fontWeight: 'bolder', color: '#00557A'}}>{product?.status_text}</span></p>
|
||||
<h4><span style={{paddingLeft: '10px'}}>{product?.name}</span></h4>
|
||||
<h4><span className='text-truncate' style={{paddingLeft: '10px'}}>{product?.name}</span></h4>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -31,7 +31,7 @@ export default function ProductsURL() {
|
||||
{/*<a className="btn btn-xs" href="#!">Export <i className="zmdi zmdi-download pl-1"></i> </a>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body scrollbar scroll_dark pt-0" style={{maxHeight: '350px'}}>
|
||||
<div className="overflow-y-auto card-body scrollbar scroll_dark pt-0" style={{maxHeight: '350px'}}>
|
||||
<div className="datatable-wrapper table-responsive">
|
||||
{isFetching ?
|
||||
<>
|
||||
|
||||
@@ -77,7 +77,7 @@ export default function RecentActions() {
|
||||
<h4>{dataAction?.data?.completed}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-responsive m-t-20">
|
||||
<div className="overflow-y-auto table-responsive m-t-20">
|
||||
<table id="datatable-buttons" className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -94,7 +94,7 @@ export default function RecentActions() {
|
||||
let text = action?.status == '5' ? 'completed' : action?.status == '3' ? 'verifying' : action?.status == '0' ? 'processing' : 'processing'
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{action?.id}</td>
|
||||
<td>{(action?.id).toString().slice(-4)}</td>
|
||||
<td>{action?.action_label}</td>
|
||||
<td>{new Date(action?.added).toDateString()}</td>
|
||||
<td>
|
||||
|
||||
@@ -7,7 +7,7 @@ import siteLinks from "../../../links/siteLinks";
|
||||
|
||||
export default function UserHeader(){
|
||||
|
||||
const { userDetails } = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
const { userDetails } = useSelector((state) => state?.userDetails); // USER Details
|
||||
|
||||
const nav_menu = useRef(null)
|
||||
|
||||
@@ -78,6 +78,7 @@ export default function UserHeader(){
|
||||
<span className="bg-success user-status"></span>
|
||||
</a>
|
||||
<div ref={nav_menu} onClick={toggleMenu} className="dropdown-menu animated fadeIn">
|
||||
<div className="position-fixed" style={{top: '0px', left: '0px', right: '0px', bottom: '0px'}}></div>
|
||||
<div className="bg-gradient px-4 py-3">
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<div className="mr-1">
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import React, { useMemo, useRef, useState } from "react";
|
||||
import React, {useEffect, useMemo, useRef, useState} from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import getImage from "../../utils/getImage";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { productRefreshSite, getSettingsData } from "../../services/services";
|
||||
import Settings from "./settingsTab/Settings";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
import {SocketContextValues} from "../context/SocketIOContext";
|
||||
|
||||
|
||||
export default function ProductActive({productData}){
|
||||
|
||||
const {joinRoom} = SocketContextValues() // Destructures values from socket context
|
||||
const iframe = useRef()
|
||||
|
||||
const [refreshMsg, setRefreshMsg] = useState('')
|
||||
|
||||
const refresh = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return productRefreshSite(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
setRefreshMsg(res?.data?.message)
|
||||
setTimeout(()=>{setRefreshMsg('')},3000)
|
||||
iframe.current.src += ''
|
||||
}
|
||||
})
|
||||
@@ -31,6 +36,13 @@ export default function ProductActive({productData}){
|
||||
}
|
||||
let externalUrl= 'https://'+productData?.internal_url
|
||||
|
||||
const productSubUID = productData.subscription_uid;
|
||||
useEffect(() => {
|
||||
const provision_room = "PROVISION_"+productSubUID;
|
||||
console.log("JOINING ROOM ON ACTIVE *** ", provision_room);
|
||||
joinRoom(provision_room); // provision subscription room
|
||||
}, [])
|
||||
|
||||
return(
|
||||
<>
|
||||
{/*<BreadcrumbComBS title='Active Product Name' paths={['Dashboard', 'Product']} />*/}
|
||||
@@ -54,12 +66,17 @@ export default function ProductActive({productData}){
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="card-body" style={{minHeight: '680px'}}>
|
||||
<iframe ref={iframe} style={{borderWidth: '0px'}} src={externalUrl} width="100%" height="600" title={externalUrl}></iframe>
|
||||
</div>
|
||||
<div className="p-4 ml-auto">
|
||||
<button type="button" onClick={handleRefresh} className="btn btn-primary">{refresh.isPending ? 'Loading...' : 'Refresh Site'}
|
||||
</button>
|
||||
<div className="d-flex justify-end gap-3">
|
||||
{refreshMsg &&
|
||||
<p className="text-success text-center">{refreshMsg}</p>
|
||||
}
|
||||
<button type="button" onClick={handleRefresh} className="btn btn-primary">{refresh.isPending ? 'Initiating...' : 'Rebuild Site'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,7 +87,7 @@ export default function ProductActive({productData}){
|
||||
<h4 className="card-title"> Site Settings </h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="card-body" style={{minHeight: '680px'}}>
|
||||
<Settings productData={productData} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,39 +1,41 @@
|
||||
import { useEffect } from "react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import {useEffect} from "react";
|
||||
import {useQuery} from "@tanstack/react-query";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
import { productProvision } from "../../services/services";
|
||||
import {productProvision} from "../../services/services";
|
||||
import getImage from "../../utils/getImage";
|
||||
import { SocketContextValues } from "../context/SocketIOContext";
|
||||
import {SocketContextValues} from "../context/SocketIOContext";
|
||||
|
||||
|
||||
export default function ProductProvision(props){
|
||||
export default function ProductProvision(props) {
|
||||
const {joinRoom} = SocketContextValues() // Destructures values from socket context
|
||||
|
||||
const productTitle = props?.productData?.title;
|
||||
const productDescription = props?.productData?.description;
|
||||
const productTitle = props?.productData?.title;
|
||||
const productDescription = props?.productData?.description;
|
||||
const productID = props?.productData?.product_id
|
||||
const productUID = props?.productData?.product_uid
|
||||
const productSubUID = props?.productData?.product_subscription_uid
|
||||
|
||||
const reqData = {
|
||||
product_id : productID,
|
||||
product_id: productID,
|
||||
product_subscription_uid: productSubUID
|
||||
}
|
||||
|
||||
const {data:provision, isFetching, isError, error} = useQuery({
|
||||
const {data: provision, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.myproduct_provision,
|
||||
queryFn: () => productProvision(reqData)
|
||||
})
|
||||
|
||||
const provisionData = provision?.data
|
||||
|
||||
useEffect(()=>{
|
||||
joinRoom(productSubUID); // provision subscription room
|
||||
},[])
|
||||
useEffect(() => {
|
||||
const provision_room = "PROVISION_" + productSubUID;
|
||||
console.log("JOINING ROOM ON START *** ", provision_room);
|
||||
joinRoom(provision_room); // provision subscription room
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
{isFetching ?
|
||||
{isFetching ?
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
@@ -42,82 +44,87 @@ export default function ProductProvision(props){
|
||||
</div>
|
||||
</>
|
||||
: isError ?
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{error.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{error.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Creating - {productTitle} </h4>
|
||||
<h4 className="card-title">Creating - {productTitle} </h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="progress">
|
||||
<div className="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
|
||||
aria-valuenow={`${provisionData?.percent_completed}%`} aria-valuemin="0" aria-valuemax="100" style={{width:`${provisionData?.percent_completed}%`}} ></div>
|
||||
<div className="progress-bar progress-bar-striped progress-bar-animated"
|
||||
role="progressbar"
|
||||
aria-valuenow={`${provisionData?.percent_completed}%`}
|
||||
aria-valuemin="0" aria-valuemax="100"
|
||||
style={{width: `${provisionData?.percent_completed}%`}}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
<div className="row">
|
||||
<div className="col-lg-6">
|
||||
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Progress Information</h4>
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Progress Information</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="table-responsive">
|
||||
<table className="table table-info mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{width: '10px'}}>#</th>
|
||||
<th scope="col">Action</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{provisionData?.activities?.map(item => (
|
||||
<tr key={item.id}>
|
||||
<th scope="row">{item.id}</th>
|
||||
<td>{item.action}</td>
|
||||
<div className="card-body">
|
||||
<div className="table-responsive">
|
||||
<table className="table table-info mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" style={{width: '10px'}}>#</th>
|
||||
<th scope="col">Action</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{provisionData?.activities?.map(item => (
|
||||
<tr key={item.id}>
|
||||
<th scope="row">{item.id}</th>
|
||||
<td>{item.action}</td>
|
||||
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-lg-6">
|
||||
<div className="card card-statistics ">
|
||||
<h4 className="card-title" style={{padding:'10px'}}>Started creating your selection</h4>
|
||||
<img className="card-img-top" src={getImage('widget/working.jpg')} alt="Card image cap" />
|
||||
{/* <div className="card-body">
|
||||
<div className="col-lg-6">
|
||||
<div className="card card-statistics ">
|
||||
<h4 className="card-title" style={{padding: '10px'}}>Started creating your
|
||||
selection</h4>
|
||||
<img className="card-img-top" src={getImage('widget/working.jpg')}
|
||||
alt="Card image cap"/>
|
||||
{/* <div className="card-body">
|
||||
<div className="" dangerouslySetInnerHTML={{__html: productDescription}}/>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -126,7 +126,7 @@ export default function ProductStart(props){
|
||||
</div>
|
||||
|
||||
{/* Vertical Center Modal */}
|
||||
<div ref={modalRef} className="modal fade" id="verticalCenter" tabIndex="-1" role="dialog" aria-hidden="true">
|
||||
<div ref={modalRef} className="modal fade" id="verticalCenter" tabIndex="-1" role="dialog" aria-hidden="false">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
import React, {memo} from 'react'
|
||||
import getImage from "../../../utils/getImage";
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
||||
import queryKeys from '../../../services/queryKeys';
|
||||
import {
|
||||
getProductcolorStyleCss,
|
||||
activateTemplate,
|
||||
getProductColorStyles,
|
||||
activateColorStyle
|
||||
} from '../../../services/services';
|
||||
import {Link} from "react-router-dom";
|
||||
import siteLinks from "../../../links/siteLinks";
|
||||
|
||||
const ColorStyleConfigure = memo(({name = 'Full Name', data, productData}) => {
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const {data: colorStyleCss, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.productcolorStyleCss,
|
||||
queryFn: () => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
product_id: productData?.product_id
|
||||
}
|
||||
return getProductColorStyles(reqData)
|
||||
},
|
||||
staleTime: 0
|
||||
})
|
||||
|
||||
const templateResponse = colorStyleCss?.data
|
||||
const currentColorUID = templateResponse?.current_colorstyle_uid
|
||||
const color_styles = templateResponse?.color_styles
|
||||
const custom_template_name = templateResponse?.custom_template_name
|
||||
|
||||
// console.log('data Template', templateResponse)
|
||||
console.log("Page data == ", data)
|
||||
|
||||
const handleActivateTemplate = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return activateColorStyle(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if (res?.data?.resultCode != '0') {
|
||||
throw new Error(res.data.resultDescription)
|
||||
}
|
||||
queryClient.refetchQueries({ // refetches productProvision API call
|
||||
queryKey: [...queryKeys.settingsData],
|
||||
})
|
||||
},
|
||||
onSettled: () => {
|
||||
setTimeout(() => {
|
||||
handleActivateTemplate.reset()
|
||||
}, 3000)
|
||||
}
|
||||
})
|
||||
|
||||
const handleSubmit = (style_uid) => {
|
||||
const reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
product_id: productData?.product_id,
|
||||
color_style_uid: style_uid
|
||||
}
|
||||
// console.log(reqData)
|
||||
handleActivateTemplate.mutate(reqData)
|
||||
}
|
||||
if (custom_template_name && custom_template_name != '') {
|
||||
// This implies we have a custom template , just return here
|
||||
return <>
|
||||
<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'
|
||||
style={{marginBottom: '20px'}}>Custom Product Template.</h4>
|
||||
<img className='' style={{width: '200px'}}
|
||||
src={getImage('custom-template.png')}
|
||||
alt='mail-alert'/>
|
||||
<h4 className='p-4 text-black'
|
||||
style={{marginTop: '20px'}}>This product is using a custom template named <span
|
||||
style={{color: 'darkred'}}>“{custom_template_name}”</span> .</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
}
|
||||
return (
|
||||
<div className="page-account-form">
|
||||
<div className="p-0">
|
||||
{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="row overflow-y-auto" style={{maxHeight: '550px'}}>
|
||||
<>
|
||||
{!color_styles?.length ?
|
||||
<p>No data Found</p>
|
||||
:
|
||||
color_styles.map(color_style => (
|
||||
<div key={color_style.color_style_uid} className="col-xl-6 col-sm-6">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-body" style={{
|
||||
backgroundColor: `#${color_style.color_code}`,
|
||||
opacity: '0.85',
|
||||
borderRadius: '10px'
|
||||
}}>
|
||||
<div className="text-center p-2">
|
||||
{/*<div className="mb-2">*/}
|
||||
{/* <img src={getImage('file-icon/svg.png')}*/}
|
||||
{/* alt={template.title}/>*/}
|
||||
{/*</div>*/}
|
||||
<h4 className="mb-0">{color_style.title}</h4>
|
||||
{currentColorUID === color_style.color_style_uid ?
|
||||
<button className="btn btn-light"
|
||||
disabled={true}>Active</button>
|
||||
:
|
||||
<button
|
||||
onClick={() => handleSubmit(color_style.color_style_uid)}
|
||||
className="btn btn-primary">Select</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{/* {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 className="col-12">
|
||||
<>
|
||||
{handleActivateTemplate.isPending ?
|
||||
<p className={'text-center '}>loading...</p>
|
||||
:
|
||||
handleActivateTemplate.isError ?
|
||||
<p className={'text-center text-danger'}>{handleActivateTemplate.error.message}</p>
|
||||
:
|
||||
handleActivateTemplate.isSuccess ?
|
||||
<p className={'text-center text-success'}>Templated activated
|
||||
successfully</p>
|
||||
:
|
||||
null
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
export default ColorStyleConfigure
|
||||
@@ -6,8 +6,18 @@ import NoYesBooleanDropdown from './NoYesBooleanDropdown';
|
||||
import {IoMdArrowDropdown} from 'react-icons/io';
|
||||
import queryKeys from '../../../services/queryKeys';
|
||||
import sortObjectByListOrder from '../../../helpers/sortObjectByListOrder';
|
||||
import URLConfiguration from "./URLConfiguration";
|
||||
import ColorStyleConfigure from "./ColorStyleConfigure";
|
||||
|
||||
const GeneralTab = memo(({name = 'Full Name', data, isCustom, productData, backendValues, setFieldsChanged}) => {
|
||||
const GeneralTab = memo(({
|
||||
name = 'Full Name',
|
||||
data,
|
||||
tabKey,
|
||||
isCustom,
|
||||
productData,
|
||||
backendValues,
|
||||
setFieldsChanged
|
||||
}) => {
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
@@ -81,7 +91,7 @@ const GeneralTab = memo(({name = 'Full Name', data, isCustom, productData, backe
|
||||
}
|
||||
submitSettings.mutate(reqData)
|
||||
}
|
||||
|
||||
console.log(tabKey);
|
||||
return (
|
||||
<>
|
||||
{backendValues?.isFetching || !backendValues?.data ?
|
||||
@@ -101,8 +111,17 @@ const GeneralTab = memo(({name = 'Full Name', data, isCustom, productData, backe
|
||||
:
|
||||
<>
|
||||
{isCustom === true ?
|
||||
<SiteTemplateSelector name={name} data={sortedData} isCustom={isCustom}
|
||||
productData={productData}/>
|
||||
<>
|
||||
{(tabKey === 'template_tab') &&
|
||||
<SiteTemplateSelector name={name} data={sortedData} isCustom={isCustom}
|
||||
productData={productData}/>}
|
||||
{(tabKey === 'url_config_tab') &&
|
||||
<URLConfiguration name={name} data={sortedData} isCustom={isCustom}
|
||||
productData={productData}/>}
|
||||
{(tabKey === 'color_scheme_tab') &&
|
||||
<ColorStyleConfigure name={name} data={sortedData} isCustom={isCustom}
|
||||
productData={productData}/>}
|
||||
</>
|
||||
:
|
||||
<div className="page-account-form">
|
||||
<div className="p-0" style={{minHeight: '500px'}}>
|
||||
|
||||
@@ -109,7 +109,7 @@ const Settings = memo(({productData}) => {
|
||||
// id={value.controls} role="tabpanel"
|
||||
// aria-labelledby={key}
|
||||
>
|
||||
<GeneralTab name={value.title} data={value.data} isCustom={value.custom} productData={productData} backendValues={settingsData} setFieldsChanged={setFieldsChanged} />
|
||||
<GeneralTab tabKey={key} name={value.title} data={value.data} isCustom={value.custom} productData={productData} backendValues={settingsData} setFieldsChanged={setFieldsChanged} />
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import React, {memo} from 'react'
|
||||
import getImage from "../../../utils/getImage";
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
|
||||
import queryKeys from '../../../services/queryKeys';
|
||||
import { getProductTemplateData, activateTemplate } from '../../../services/services';
|
||||
import {getProductTemplateData, activateTemplate} from '../../../services/services';
|
||||
import {Link} from "react-router-dom";
|
||||
import siteLinks from "../../../links/siteLinks";
|
||||
|
||||
const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
const SiteTemplateSelector = memo(({name = 'Full Name', data, productData}) => {
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const {data:templateData, isFetching, isError, error} = useQuery({
|
||||
const {data: templateData, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.productTemplateData,
|
||||
queryFn: () => {
|
||||
let reqData = {
|
||||
@@ -16,7 +18,7 @@ const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
product_id: productData?.product_id
|
||||
}
|
||||
return getProductTemplateData(reqData)
|
||||
return getProductTemplateData(reqData)
|
||||
},
|
||||
staleTime: 0
|
||||
})
|
||||
@@ -24,16 +26,17 @@ const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
const templateResponse = templateData?.data
|
||||
const currentTemUID = templateResponse?.current_template_uid
|
||||
const templates = templateResponse?.templates
|
||||
const custom_template_name = templateResponse?.custom_template_name
|
||||
|
||||
// console.log('data Template', templateResponse)
|
||||
// console.log("Page data == ", data)
|
||||
console.log("Page data == ", data)
|
||||
|
||||
const handleActivateTemplate = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return activateTemplate(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if(res?.data?.resultCode != '0'){
|
||||
if (res?.data?.resultCode != '0') {
|
||||
throw new Error(res.data.resultDescription)
|
||||
}
|
||||
queryClient.refetchQueries({ // refetches productProvision API call
|
||||
@@ -41,7 +44,7 @@ const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
})
|
||||
},
|
||||
onSettled: () => {
|
||||
setTimeout(()=>{
|
||||
setTimeout(() => {
|
||||
handleActivateTemplate.reset()
|
||||
}, 3000)
|
||||
}
|
||||
@@ -57,51 +60,73 @@ const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
// console.log(reqData)
|
||||
handleActivateTemplate.mutate(reqData)
|
||||
}
|
||||
if (custom_template_name && custom_template_name != '') {
|
||||
// This implies we have a custom template , just return here
|
||||
return <>
|
||||
<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'
|
||||
style={{marginBottom: '20px'}}>Custom Product Template.</h4>
|
||||
<img className='' style={{width: '200px'}}
|
||||
src={getImage('custom-template.png')}
|
||||
alt='mail-alert'/>
|
||||
<h4 className='p-4 text-black'
|
||||
style={{marginTop: '20px'}}>This product is using a custom template named <span
|
||||
style={{color: 'darkred'}}>“{custom_template_name}”</span> .</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
}
|
||||
return (
|
||||
<div className="page-account-form">
|
||||
<div className="p-0">
|
||||
{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="row">
|
||||
{isFetching ?
|
||||
<>
|
||||
{!templates?.length ?
|
||||
<p>No data Found</p>
|
||||
:
|
||||
templates.map(template => (
|
||||
<div key={template.template_uid} 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('file-icon/svg.png')} alt={template.title} />
|
||||
</div>
|
||||
<h4 className="mb-0">{template.title}</h4>
|
||||
{currentTemUID == template.template_uid ?
|
||||
<button className="btn btn-light" disabled={true}>Active</button>
|
||||
:
|
||||
<button onClick={()=>handleSubmit(template.template_uid)} className="btn btn-primary">Activate</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className='text-mute'>Loading...</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{/* {Object.entries(data)?.map(([key, value]) => (
|
||||
</div>
|
||||
</>
|
||||
: isError ?
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{error?.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="row overflow-y-auto" style={{maxHeight: '550px'}}>
|
||||
<>
|
||||
{!templates?.length ?
|
||||
<p>No data Found</p>
|
||||
:
|
||||
templates.map(template => (
|
||||
<div key={template.template_uid} 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('file-icon/svg.png')}
|
||||
alt={template.title}/>
|
||||
</div>
|
||||
<h4 className="mb-0">{template.title}</h4>
|
||||
{currentTemUID == template.template_uid ?
|
||||
<button className="btn btn-light"
|
||||
disabled={true}>Active</button>
|
||||
:
|
||||
<button onClick={() => handleSubmit(template.template_uid)}
|
||||
className="btn btn-primary">Activate</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
{/* {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">
|
||||
@@ -116,24 +141,25 @@ const SiteTemplateSelector = memo(({name='Full Name', data, productData}) =>{
|
||||
</div>
|
||||
</div>
|
||||
))} */}
|
||||
</>
|
||||
|
||||
<div className="col-12">
|
||||
<>
|
||||
{handleActivateTemplate.isPending ?
|
||||
<p className={'text-center '}>loading...</p>
|
||||
:
|
||||
handleActivateTemplate.isError ?
|
||||
<p className={'text-center text-danger'}>{handleActivateTemplate.error.message}</p>
|
||||
:
|
||||
handleActivateTemplate.isSuccess?
|
||||
<p className={'text-center text-success'}>Templated activated successfully</p>
|
||||
:
|
||||
null
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
<div className="col-12">
|
||||
<>
|
||||
{handleActivateTemplate.isPending ?
|
||||
<p className={'text-center '}>loading...</p>
|
||||
:
|
||||
handleActivateTemplate.isError ?
|
||||
<p className={'text-center text-danger'}>{handleActivateTemplate.error.message}</p>
|
||||
:
|
||||
handleActivateTemplate.isSuccess ?
|
||||
<p className={'text-center text-success'}>Templated activated
|
||||
successfully</p>
|
||||
:
|
||||
null
|
||||
}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import {Form, Formik} from "formik";
|
||||
import * as Yup from "yup";
|
||||
import {useMutation} from '@tanstack/react-query';
|
||||
import {setExternalURL} from '../../../services/services';
|
||||
import { useState } from "react";
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
url: Yup.string().required("URL is required").matches(/^https?:\/\/[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-]+\.[a-zA-Z]+/, 'Must be like: https://example.mysite.com'),
|
||||
})
|
||||
|
||||
// const initialValues = {
|
||||
// url: '',
|
||||
// };
|
||||
|
||||
const URLConfiguration = ({productData}) => {
|
||||
|
||||
const [externalURLChanged, setExternalURLChanged] = useState(true)
|
||||
|
||||
const initialValues = {
|
||||
url: productData?.external_url || '',
|
||||
};
|
||||
|
||||
let defaultUrl = 'https://' + productData?.internal_url
|
||||
let externalUrl = productData?.external_url
|
||||
|
||||
const handleExternalURLChanged = (e) => {
|
||||
if(e.target.value == externalUrl){
|
||||
setExternalURLChanged(true)
|
||||
}else{
|
||||
setExternalURLChanged(false)
|
||||
}
|
||||
}
|
||||
|
||||
// API to set url
|
||||
const setURL = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return setExternalURL(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if (res.data.resultCode != '0') {
|
||||
// throw({message: res?.data?.resultDescription})
|
||||
throw({message: 'Something went wrong!'})
|
||||
}
|
||||
},
|
||||
onSettled: () => {
|
||||
setTimeout(() => {
|
||||
setURL.reset()
|
||||
}, 3000)
|
||||
}
|
||||
// onError: (err) => {
|
||||
// console.log('err', err)
|
||||
// }
|
||||
})
|
||||
|
||||
const handleSubmit = (values) => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
subscription_uid: productData?.subscription_uid,
|
||||
external_url: values.url
|
||||
}
|
||||
setURL.mutate(reqData)
|
||||
}
|
||||
|
||||
return <>
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title" style={{textTransform: 'none'}}>{defaultUrl}</h4>
|
||||
</div>
|
||||
</div>
|
||||
{/*<div className="card-body">*/}
|
||||
{/* <div className="form-group">*/}
|
||||
{/* /!*<label htmlFor="exampleInputEmail1">Email address</label>*!/*/}
|
||||
{/* <input type="email" className="form-control"*/}
|
||||
{/* aria-describedby="defaultUrlHelp" value={defaultUrl} readOnly={true} />*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='w-full'>
|
||||
<div className="card card-statistics" style={{backgroundColor: '#b6e5ef'}}>
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title" style={{textTransform: 'none'}}>Set your own URL</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="form-group">
|
||||
<label htmlFor="exampleInputEmail1">Enter your full URL <span
|
||||
className={`${(props.errors.url && props.touched.url) && 'text-danger'}`}>{props.errors.url}</span></label>
|
||||
<input value={props.values.url} onChange={(e)=>{props.handleChange(e); handleExternalURLChanged(e)}} type="text"
|
||||
className="form-control" id="url" aria-describedby="url"
|
||||
placeholder="https://example.mysite.com"/>
|
||||
</div>
|
||||
<div style={{width: '100%', textAlign: 'right'}}>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={setURL.isPending || externalURLChanged}
|
||||
className="btn btn-primary"
|
||||
>
|
||||
{setURL.isPending ? 'Loading...' : 'Submit'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{setURL.error &&
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{setURL.error.message}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
{setURL.isSuccess &&
|
||||
<div className="col-12">
|
||||
<p className='text-success'>{'Completed successfully'}</p>
|
||||
</div>
|
||||
}
|
||||
<div style={{backgroundColor: '#94b8c0', borderRadius: '10px', padding: '10px'}}>
|
||||
Final steps to configure your URL:<br/>
|
||||
DNS:<br/>
|
||||
DNS:<br/>
|
||||
DNS:<br/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
|
||||
</>
|
||||
}
|
||||
|
||||
export default URLConfiguration
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, {useEffect, useMemo, useState} from "react";
|
||||
import React, {useCallback, useEffect, useMemo, useState} from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
// import { useLocation } from "react-router-dom";
|
||||
// import { Form, Formik } from "formik";
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import {useMutation, useQuery} from "@tanstack/react-query";
|
||||
import getImage from "../../utils/getImage";
|
||||
@@ -13,17 +13,19 @@ import {updateUserDetails} from "../../store/UserDetails";
|
||||
import {useDispatch} from "react-redux";
|
||||
|
||||
|
||||
// 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: '',
|
||||
// };
|
||||
const validationSchema = Yup.object().shape({
|
||||
practice: Yup.string().required("Required"),
|
||||
specialization: Yup.string().when('practice', {
|
||||
is: (value) => typeof value === 'string' && value.trim().length > 0,
|
||||
then: (schema) => schema.required('Required'),
|
||||
otherwise: (schema) => schema,
|
||||
}),
|
||||
introduction: Yup.string().min(1, "Minimum 1 character").max(50, "Maximum 50 characters"),
|
||||
url_name: Yup.string().min(6, "Minimum 6 characters").max(16, "Maximum 16 characters").required("Required").matches(
|
||||
/^[a-zA-Z0-9]+$/, // Regex for alphanumeric characters
|
||||
'Must contain only alphanumeric characters' // Custom error message
|
||||
),
|
||||
})
|
||||
|
||||
|
||||
export default function ProfileCompleteCom() {
|
||||
@@ -35,28 +37,27 @@ export default function ProfileCompleteCom() {
|
||||
const {state: {redirectLink}} = useLocation()
|
||||
|
||||
const [practices, setPractices] = useState([])
|
||||
const [specialties, setSpecialties] = useState([])
|
||||
|
||||
const [initialValues, setInitialValues] = useState({
|
||||
practice: '',
|
||||
specialization: '',
|
||||
introduction: '',
|
||||
url_name: ''
|
||||
})
|
||||
|
||||
const specialties = useMemo(() => { // FUNCTION TO UPDATE SPECIALITY ARRAY EACH TIME PRACTICE CHANGES
|
||||
const handleUpdateSpecialties = (e) => {
|
||||
setInitialValues(prev => ({...prev, specialization: ''}))
|
||||
if (!initialValues.practice) {
|
||||
return []
|
||||
}
|
||||
const specialtiesArr = practices.filter(item => item.practice == initialValues.practice)[0]?.specialties
|
||||
return specialtiesArr
|
||||
}, [initialValues.practice])
|
||||
const specialtiesArr = practices.filter(item => item.practice == e.target.value)[0]?.specialties
|
||||
setSpecialties(specialtiesArr)
|
||||
}
|
||||
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
const {practice, specialization} = fields
|
||||
if (!practice || !specialization) {
|
||||
throw new Error('Please select both practice and specialization fields')
|
||||
const {practice, specialization, url_name} = fields
|
||||
if (!practice || !specialization || !url_name) {
|
||||
throw new Error('Please Select both Practice, Specialization and Enter URL_Name')
|
||||
}
|
||||
return completeProfile(fields)
|
||||
},
|
||||
@@ -93,15 +94,11 @@ export default function ProfileCompleteCom() {
|
||||
}
|
||||
})
|
||||
|
||||
const handlePracticeChange = ({target: {name, value}}) => {
|
||||
setInitialValues(prev => ({...prev, [name]: value}))
|
||||
}
|
||||
|
||||
const handleCompleteProfile = () => { // FUNCTION TO COMPLETE PROFILE
|
||||
const handleCompleteProfile = (values) => { // FUNCTION TO COMPLETE PROFILE
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
...initialValues
|
||||
...values
|
||||
}
|
||||
mutation.mutate(reqData)
|
||||
}
|
||||
@@ -145,89 +142,146 @@ export default function ProfileCompleteCom() {
|
||||
<div className="card-body">
|
||||
<div 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`}>Practice :</label>
|
||||
<div className="position-relative">
|
||||
{/* <select onChange={props.handleChange} name='practice' value={props.values.practice} className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{practices.map((practice, index)=>(
|
||||
<option key={index} value={practice.practice}>{practice.practice}</option>
|
||||
))}
|
||||
</select> */}
|
||||
<select onChange={handlePracticeChange} name='practice'
|
||||
value={initialValues.practice} className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{practices.map((practice, index) => (
|
||||
<option key={index}
|
||||
value={practice.practice}>{practice.practice}</option>
|
||||
))}
|
||||
</select>
|
||||
<IoMdArrowDropdown className='position-absolute w-auto' style={{
|
||||
top: '50%',
|
||||
right: '2px',
|
||||
transform: 'translateY(-50%)'
|
||||
}}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleCompleteProfile}
|
||||
enableReinitialize={true}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='mt-2'>
|
||||
<>
|
||||
<div className="">
|
||||
<div className="form-group position-relative">
|
||||
<label className={`text-black fw-bold control-label`}>Practice : <span className="text-danger">{(props.errors.practice && props.touched.practice) && props.errors.practice}</span></label>
|
||||
<div className="position-relative">
|
||||
{/* <select onChange={props.handleChange} name='practice' value={props.values.practice} className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{practices.map((practice, index)=>(
|
||||
<option key={index} value={practice.practice}>{practice.practice}</option>
|
||||
))}
|
||||
</select> */}
|
||||
<select
|
||||
onChange={(e) => {props.handleChange(e); props.setFieldValue('specialization', ''); handleUpdateSpecialties(e)}}
|
||||
name='practice'
|
||||
value={props.values.practice} className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{practices.map((practice, index) => (
|
||||
<option key={index}
|
||||
value={practice.practice}>{practice.practice}</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`}>Your
|
||||
Specialization :</label>
|
||||
<div className="position-relative">
|
||||
<select onChange={handlePracticeChange} name='specialization'
|
||||
value={initialValues.specialization}
|
||||
className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{specialties.map((specialty, index) => (
|
||||
<option key={index} value={specialty}>{specialty}</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`}>Your
|
||||
Specialization : <span className="text-danger">{(props.errors.specialization && props.touched.specialization) && props.errors.specialization}</span></label>
|
||||
<div className="position-relative">
|
||||
<select onChange={props.handleChange} name='specialization'
|
||||
value={props.values.specialization}
|
||||
className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{specialties.map((specialty, index) => (
|
||||
<option key={index} value={specialty}>{specialty}</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`}>Other General
|
||||
Information :</label>
|
||||
<textarea name='introduction' rows={10} style={{resize: 'none'}}
|
||||
className="form-control" value={initialValues.introduction}
|
||||
onChange={handlePracticeChange}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="form-group position-relative">
|
||||
<label className={`text-black fw-bold control-label`}>Other General Information : <span className="text-danger">{(props.errors.introduction && props.touched.introduction) && props.errors.introduction}</span></label>
|
||||
<textarea name='introduction' rows={5} style={{resize: 'none'}}
|
||||
className="form-control" value={props.values.introduction}
|
||||
onChange={props.handleChange}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="">
|
||||
<div className="form-group position-relativ'e">
|
||||
{/*<label className={`text-black fw-bold control-label`}>What we use this*/}
|
||||
{/* information for :</label>*/}
|
||||
<div style={{fontSize: '14px', borderRadius: '10px', backgroundColor: 'aliceblue', fontWeight:'bolder', padding: '15px' }}>
|
||||
MERMS A.I. agents use the information supplied to help generate useful entries for your product settings.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="">
|
||||
<div className="form-group position-relativ'e">
|
||||
{/*<label className={`text-black fw-bold control-label`}>What we use this*/}
|
||||
{/* information for :</label>*/}
|
||||
<div style={{
|
||||
fontSize: '14px',
|
||||
borderRadius: '10px',
|
||||
backgroundColor: 'aliceblue',
|
||||
fontWeight: 'bolder',
|
||||
padding: '15px'
|
||||
}}>
|
||||
MERMS A.I. agents use the information supplied to help generate
|
||||
useful entries for your product settings.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{(mutation.isError || mutation.isSuccess) &&
|
||||
<>
|
||||
<div className="">
|
||||
<p className={`${mutation.isSuccess ? 'text-success' : 'text-danger'}`}>{mutation.isSuccess ? 'Completed successfully, redirecting...' : mutation.error.message}</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
<div className="">
|
||||
<div className="form-group position-relative">
|
||||
<label className={`text-black fw-bold control-label`}>URL Name : <span className="text-danger">{(props.errors.url_name && props.touched.url_name) && props.errors.url_name}</span></label>
|
||||
<div className="position-relative d-flex flex-column flex-xxl-row" style={{gap: '10px'}}>
|
||||
{/* <select onChange={handlePracticeChange} name='url_name'
|
||||
value={initialValues.url_name} className="form-control">
|
||||
<option value=''>Select</option>
|
||||
{practices.map((practice, index) => (
|
||||
<option key={index}
|
||||
value={practice.practice}>{practice.practice}</option>
|
||||
))}
|
||||
</select>
|
||||
<IoMdArrowDropdown className='position-absolute w-auto' style={{
|
||||
top: '50%',
|
||||
right: '2px',
|
||||
transform: 'translateY(-50%)'
|
||||
}}/> */}
|
||||
<input
|
||||
className="form-control"
|
||||
onChange={props.handleChange} name='url_name'
|
||||
value={props.values.url_name}
|
||||
minLength={6}
|
||||
maxLength={16}
|
||||
/>
|
||||
<p className="border-radius-10 p-2 border border-warning"
|
||||
style={{fontSize: "1.0rem"}}>We use the URL Name to form part of
|
||||
your default URL when we configure
|
||||
a new URL for your products. You can always change your product
|
||||
URL. <br/>
|
||||
<b>Example : <span style={{color: 'red'}}>url_name</span>.product.mermsemr.com
|
||||
</b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-auto text-end">
|
||||
<button type='button' onClick={handleCompleteProfile}
|
||||
className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Continue'}</button>
|
||||
</div>
|
||||
</>
|
||||
{(mutation.isError || mutation.isSuccess) &&
|
||||
<>
|
||||
<div className="">
|
||||
<p className={`${mutation.isSuccess ? 'text-success' : 'text-danger'}`}>{mutation.isSuccess ? 'Completed successfully, redirecting...' : mutation.error.message}</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
<div className="mt-auto text-end">
|
||||
<button type='submit'
|
||||
className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Continue'}</button>
|
||||
</div>
|
||||
</>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
{/* </div> */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,55 @@ export default function Reports(){
|
||||
<>
|
||||
<BreadcrumbComBS title='Reports' paths={['Dashboard', 'Reports']} />
|
||||
<div className="row">
|
||||
<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>
|
||||
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
|
||||
<div className="card card-statistics" style={{minHeight:'550px'}}>
|
||||
{/*<div className="card-header">*/}
|
||||
{/* <div className="card-heading">*/}
|
||||
{/* <h4 className="card-title"> Tab vertical </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="home-09-tab" data-toggle="tab" href="#home-09" role="tab" aria-controls="home-09" aria-selected="true"> Home</a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" id="profile-09-tab" data-toggle="tab" href="#profile-09" role="tab" aria-controls="profile-09" aria-selected="false"> Profile </a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" id="portfolio-09-tab" data-toggle="tab" href="#portfolio-09" role="tab" aria-controls="portfolio-09" aria-selected="false">Portfolio </a>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<a className="nav-link" id="contact-09-tab" data-toggle="tab" href="#contact-09" role="tab" aria-controls="contact-09" aria-selected="false"> Contact </a>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="tab-content">
|
||||
<div className="tab-pane fade active show" id="home-09" role="tabpanel" aria-labelledby="home-09-tab">
|
||||
<p>Positive pleasure-oriented goals are much more powerful motivators than negative fear-based ones. Although each is successful separately, the right combination of both is the most powerful motivational force known to humankind.Make a list of your achievements toward your long-term goal and remind yourself that intentions don’t count, only action’s.</p>
|
||||
</div>
|
||||
<div className="tab-pane fade" id="profile-09" role="tabpanel" aria-labelledby="profile-09-tab">
|
||||
<p>Reflect and experiment until you find the right combination of motivators for your personality and your personal goals. Do it today. Remind yourself of someone you know who died suddenly and the fact that there is no guarantee that tomorrow will come.</p>
|
||||
</div>
|
||||
<div className="tab-pane fade" id="portfolio-09" role="tabpanel" aria-labelledby="portfolio-09-tab">
|
||||
<p>Commitment is something that comes from understanding that everything has its price and then having the willingness to pay that price. This is important because nobody wants to put significant effort into something, only to find out after the fact that the price was too high. We all know people who live this truth.Give yourself the power of responsibility.</p>
|
||||
</div>
|
||||
<div className="tab-pane fade" id="contact-09" role="tabpanel" aria-labelledby="contact-09-tab">
|
||||
<p>I truly believe Augustine’s words are true and if you look at history you know it is true. There are many people in the world with amazing talents who realize only a small percentage of their potential. We all know people who live this truth.Give yourself the power of responsibility. Remind yourself the only thing stopping you is yourself.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { Modal } from "bootstrap";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { updateLinks } from "../../services/services";
|
||||
import queryKeys from '../../services/queryKeys';
|
||||
|
||||
|
||||
const linksValidationSchema = Yup.object().shape({
|
||||
// facebook_url: Yup.string().required("facebook is required"),
|
||||
// twitter_url: Yup.string().required("twitter is required"),
|
||||
// blogger_url: Yup.string().required("blog is required"),
|
||||
// google_url: Yup.string().required("google is required"),
|
||||
// linked_url: Yup.string().required("linkedin is required"),
|
||||
// website_url: Yup.string().required("website is required"),
|
||||
})
|
||||
|
||||
export default function LinksForm({data}) {
|
||||
const modalRef = useRef(null)
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const [intialData] = useState(data)
|
||||
|
||||
const [infoToUpdate, setInfoToUpdate] = useState({})
|
||||
|
||||
const dismissModal = () => {
|
||||
const body = document.querySelector('body')
|
||||
body.removeAttribute('style')
|
||||
// body.classList.toggle('modal-open')
|
||||
|
||||
const modalBackdrop = document.querySelectorAll('.modal-backdrop')
|
||||
modalBackdrop.forEach(item => {
|
||||
if (item) {
|
||||
item.remove();
|
||||
}
|
||||
})
|
||||
|
||||
const modal = Modal.getInstance(modalRef.current);
|
||||
modal && modal.hide();
|
||||
};
|
||||
|
||||
// UPDATE LINKS MUTATION
|
||||
const updateLinksMutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return updateLinks(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if(res.data.resultCode != '0'){
|
||||
throw({message: res?.data?.resultDescription ? res?.data?.resultDescription : 'En error occured'})
|
||||
}
|
||||
},
|
||||
onSettled: ()=>{
|
||||
setTimeout(() => {
|
||||
dismissModal() //CLOSE MODAL HERE
|
||||
queryClient.refetchQueries({
|
||||
queryKey: [...queryKeys.profile_data], // type: 'active', // exact: true,
|
||||
})
|
||||
updateLinksMutation.reset()
|
||||
}, 3000);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const handleSetInfoToUpdate = (values, helpers) => {
|
||||
setInfoToUpdate(values)
|
||||
var modal = new Modal(document.getElementById('modal_links'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
const proceed = () => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
...infoToUpdate
|
||||
}
|
||||
console.log(reqData)
|
||||
// updateLinksMutation.mutate(reqData)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Formik
|
||||
initialValues={intialData}
|
||||
validationSchema={linksValidationSchema}
|
||||
onSubmit={handleSetInfoToUpdate}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className=''>
|
||||
<div className="form-group">
|
||||
<label htmlFor="fb">Facebook URL: {(props.errors.facebook_url && props.touched.facebook_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="facebook_url" value={props.values?.facebook_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="tr">Twitter URL: {(props.errors.twitter_url && props.touched.twitter_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="twitter_url" value={props.values?.twitter_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="br">Blogger URL: {(props.errors.blogger_url && props.touched.blogger_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="blogger_url" value={props.values?.blogger_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="go">Google+ URL: {(props.errors.google_url && props.touched.google_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="google_url" value={props.values?.google_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="li">LinkedIn URL: {(props.errors.linked_url && props.touched.linked_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="linked_url" value={props.values?.linked_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="we">Website URL: {(props.errors.website_url && props.touched.website_url) && <span className="text-danger">*</span>}</label>
|
||||
<input type="text" className="form-control" name="website_url" value={props.values?.website_url} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div style={{textAlign: "right"}}>
|
||||
<button type="submit" className="btn btn-primary">Update Links
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
|
||||
{/* Vertical Center Modal */}
|
||||
<div ref={modalRef} className="modal fade" id="modal_links" tabIndex="-1" role="dialog" aria-hidden="true">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
{/* <h5 className="modal-title" style={{fontSize: '18px'}} id="verticalCenterTitle">{'productTitle'}</h5> */}
|
||||
<button type="button" className="close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<h5 className="text-center" style={{fontSize: '18px'}}>Are you sure, you want to update? gg</h5>
|
||||
{(updateLinksMutation.error || updateLinksMutation.isSuccess) && (
|
||||
<div className="col-12">
|
||||
<p className={`p-2 text-center ${updateLinksMutation.isSuccess ? 'text-success' : 'text-danger'}`}>
|
||||
{updateLinksMutation.isSuccess ? 'Updated Successfully' : updateLinksMutation.error.message}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" className="btn btn-primary" disabled={updateLinksMutation.isSuccess} onClick={proceed}>{updateLinksMutation.isPending ? 'Updating...' : 'Update'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* END of Vertical Center Modal */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import { Modal } from "bootstrap";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { updateProfile } from "../../services/services";
|
||||
import queryKeys from '../../services/queryKeys';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { updateUserDetails } from '../../store/UserDetails'
|
||||
|
||||
const profileValidationSchema = Yup.object().shape({
|
||||
firstname: Yup.string().required("firstname is required"),
|
||||
lastname: Yup.string().required("lastname is required"),
|
||||
email: Yup.string().required("email is required"),
|
||||
account_name: Yup.string().required("account name is required"),
|
||||
phone: Yup.string().required("phone is required"),
|
||||
full_address: Yup.string().required("full address is required"),
|
||||
})
|
||||
|
||||
export default function ProfileForm({data}) {
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const modalRef = useRef(null)
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const [intialData] = useState(data)
|
||||
|
||||
const [infoToUpdate, setInfoToUpdate] = useState({})
|
||||
|
||||
const dismissModal = () => {
|
||||
const body = document.querySelector('body')
|
||||
body.removeAttribute('style')
|
||||
// body.classList.toggle('modal-open')
|
||||
|
||||
const modalBackdrop = document.querySelectorAll('.modal-backdrop')
|
||||
modalBackdrop.forEach(item => {
|
||||
if (item) {
|
||||
item.remove();
|
||||
}
|
||||
})
|
||||
|
||||
const modal = Modal.getInstance(modalRef.current);
|
||||
modal && modal.hide();
|
||||
};
|
||||
|
||||
// UPDATE PROFILE MUTATION
|
||||
const updateProfileMutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return updateProfile(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
if(res.data.resultCode != '0'){
|
||||
throw({message: res?.data?.resultDescription ? res?.data?.resultDescription : 'En error occured'})
|
||||
}
|
||||
const account_name = res?.data?.personal_data?.account_name
|
||||
dispatch(updateUserDetails({ account_name }));
|
||||
},
|
||||
onSettled: ()=>{
|
||||
setTimeout(() => {
|
||||
dismissModal() //CLOSE MODAL HERE
|
||||
queryClient.refetchQueries({
|
||||
queryKey: [...queryKeys.profile_data], // type: 'active', // exact: true,
|
||||
})
|
||||
updateProfileMutation.reset()
|
||||
}, 3000);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const handleSetInfoToUpdate = (values, helpers) => {
|
||||
delete values.email
|
||||
delete values.country
|
||||
setInfoToUpdate(values)
|
||||
var modal = new Modal(document.getElementById('modal'));
|
||||
modal.show();
|
||||
}
|
||||
|
||||
const proceed = () => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid'), // USER UID
|
||||
...infoToUpdate
|
||||
}
|
||||
updateProfileMutation.mutate(reqData)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Formik
|
||||
initialValues={intialData}
|
||||
validationSchema={profileValidationSchema}
|
||||
onSubmit={handleSetInfoToUpdate}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className=''>
|
||||
<div className="form-row">
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">First Name {(props.errors.firstname && props.touched.firstname) && <span className="text-danger">{props.errors.firstname}*</span>}</label>
|
||||
<input type="text" className="form-control" name="firstname" value={props.values?.firstname} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">Last Name {(props.errors.lastname && props.touched.lastname) && <span className="text-danger">{props.errors.lastname}*</span>}</label>
|
||||
<input type="text" className="form-control" name="lastname" value={props.values?.lastname} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">Account Name {(props.errors.account_name && props.touched.account_name) && <span className="text-danger">{props.errors.account_name}*</span>}</label>
|
||||
<input type="text" className="form-control" name="account_name" value={props.values?.account_name} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="phone1">Phone Number {(props.errors.phone && props.touched.phone) && <span className="text-danger">{props.errors.phone}*</span>}</label>
|
||||
<input type="text" className="form-control" name="phone" value={props.values?.phone} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="email1">Email {(props.errors.email && props.touched.email) && <span className="text-danger">{props.errors.email}*</span>}</label>
|
||||
<input type="text" className="form-control" name="email" readOnly value={props.values?.email} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="add1">Address {(props.errors.full_address && props.touched.full_address) && <span className="text-danger">{props.errors.full_address}*</span>}</label>
|
||||
<input type="text" className="form-control" name="full_address" value={props.values?.full_address} onChange={props.handleChange} />
|
||||
</div>
|
||||
<div style={{textAlign: "right"}}>
|
||||
<button type="submit" className="btn btn-primary">Update Profile
|
||||
</button>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
|
||||
{/* Vertical Center Modal */}
|
||||
<div ref={modalRef} className="modal fade" id="modal" tabIndex="-1" role="dialog" aria-hidden="true">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
{/* <h5 className="modal-title" style={{fontSize: '18px'}} id="verticalCenterTitle">{'productTitle'}</h5> */}
|
||||
<button type="button" className="close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<h5 className="text-center" style={{fontSize: '18px'}}>Are you sure, you want to update?</h5>
|
||||
{(updateProfileMutation.error || updateProfileMutation.isSuccess) && (
|
||||
<div className="col-12">
|
||||
<p className={`p-2 text-center ${updateProfileMutation.isSuccess ? 'text-success' : 'text-danger'}`}>
|
||||
{updateProfileMutation.isSuccess ? 'Updated Successfully' : updateProfileMutation.error.message}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" className="btn btn-primary" disabled={updateProfileMutation.isSuccess} onClick={proceed}>{updateProfileMutation.isPending ? 'Updating...' : 'Update'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* END of Vertical Center Modal */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +1,37 @@
|
||||
import React from "react";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
import getImage from "../../utils/getImage";
|
||||
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { profileDetails } from "../../services/services";
|
||||
import ProfileForm from "./ProfileForm";
|
||||
import LinksForm from "./LinksForm";
|
||||
|
||||
export default function Settings() {
|
||||
const avtarImage = "avtar/merms-user.png";
|
||||
|
||||
const [intialData, setInitialData] = useState({
|
||||
external_links: {},
|
||||
personal_data: {},
|
||||
})
|
||||
|
||||
const {data:profileInfo, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.profile_data,
|
||||
queryFn: () => {
|
||||
let reqData = {
|
||||
token: localStorage.getItem('token'), // USER TOKEN
|
||||
uid: localStorage.getItem('uid') // USER UID
|
||||
}
|
||||
return profileDetails(reqData)
|
||||
}
|
||||
})
|
||||
// const profileData = profileInfo?.data // profile data
|
||||
useMemo(()=>{
|
||||
const data = profileInfo?.data
|
||||
setInitialData({external_links: data?.external_links, personal_data: data?.personal_data})
|
||||
},[profileInfo])
|
||||
// console.log('INI', intialData)
|
||||
|
||||
return (
|
||||
<>
|
||||
<BreadcrumbComBS title='Settings' paths={['Dashboard', 'Settings']}/>
|
||||
@@ -12,184 +39,74 @@ export default function Settings() {
|
||||
{/* <div className="vh-100 col-12 flex align-items-center">Coming Soon</div>*/}
|
||||
{/*</div>*/}
|
||||
|
||||
|
||||
<div className="row account-contant">
|
||||
{isFetching ?
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<p className="text-mute">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
: isError ?
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-body p-0" style={{backgroundColor: "#f9f9fb"}}>
|
||||
<div className="row no-gutters">
|
||||
<div className="col-xl-3 pb-xl-0 pb-5 border-right">
|
||||
<div className="page-account-profil pt-5">
|
||||
<div className="profile-img text-center rounded-circle">
|
||||
<div className="pt-5">
|
||||
<div className="bg-img m-auto">
|
||||
{/*<img src="assets/img/avtar/01.jpg" className="img-fluid"*/}
|
||||
{/* alt="users-avatar" />*/}
|
||||
<img src={getImage(avtarImage)}
|
||||
className="img-fluid" alt="user"/>
|
||||
</div>
|
||||
<div className="profile pt-4">
|
||||
<h4 className="mb-1">Alice Williams</h4>
|
||||
<div style={{padding: '10px'}}>
|
||||
<hr/>
|
||||
<p className="text-danger">{error?.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className="row account-contant">
|
||||
<div className="col-12">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-body p-0" style={{backgroundColor: "#f9f9fb"}}>
|
||||
<div className="row no-gutters">
|
||||
<div className="col-xl-3 pb-xl-0 pb-5 border-right">
|
||||
<div className="page-account-profil pt-5">
|
||||
<div className="profile-img text-center rounded-circle">
|
||||
<div className="pt-5">
|
||||
<div className="bg-img m-auto">
|
||||
{/*<img src="assets/img/avtar/01.jpg" className="img-fluid"*/}
|
||||
{/* alt="users-avatar" />*/}
|
||||
<img src={getImage(avtarImage)}
|
||||
className="img-fluid" alt="user"/>
|
||||
</div>
|
||||
<div className="profile pt-4">
|
||||
<h4 className="mb-1">{intialData?.personal_data?.lastname} {intialData?.personal_data?.firstname}</h4>
|
||||
<div style={{padding: '10px'}}>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="profile-btn text-center">
|
||||
<div>
|
||||
<button className="btn btn-light text-primary mb-2">Upload New Avatar
|
||||
</button>
|
||||
<div className="profile-btn text-center">
|
||||
<div>
|
||||
<button className="btn btn-light text-primary mb-2">Upload New Avatar
|
||||
</button>
|
||||
</div>
|
||||
{/*<div>*/}
|
||||
{/* <button className="btn btn-danger">Delete</button>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
{/*<div>*/}
|
||||
{/* <button className="btn btn-danger">Delete</button>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xl-5 col-md-6 col-12 border-t border-right">
|
||||
<div className="page-account-form">
|
||||
<div className="form-titel border-bottom p-3">
|
||||
<h5 className="mb-0 py-2">Edit Your Personal Settings</h5>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<form>
|
||||
<div className="form-row">
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">First Name</label>
|
||||
<input type="text" className="form-control" id="name1"
|
||||
value="Alice"/>
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">Last Name</label>
|
||||
<input type="text" className="form-control" id="name1"
|
||||
value="Williams"/>
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="name1">Account Name</label>
|
||||
<input type="text" className="form-control" id="name1"
|
||||
value="This is the best hospital name"/>
|
||||
</div>
|
||||
{/*<div className="form-group col-md-12">*/}
|
||||
{/* <label htmlFor="title1">Email</label>*/}
|
||||
{/* <input type="text" className="form-control" id="title1"*/}
|
||||
{/* value="email@email.com" />*/}
|
||||
{/*</div>*/}
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="phone1">Phone Number</label>
|
||||
<input type="text" className="form-control" id="phone1"
|
||||
value="(01) 97 563 15613"/>
|
||||
</div>
|
||||
<div className="form-group col-md-12">
|
||||
<label htmlFor="email1">Email</label>
|
||||
<input type="email" className="form-control" id="email1"
|
||||
value="alicewilliams@gmail.com"/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="add1">Address</label>
|
||||
<input type="text" className="form-control" id="add1"
|
||||
value="17504 Carlton Cuevas Rd, Gulfport, MS, 39503"/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="add2">Address 2</label>
|
||||
<input type="text" className="form-control" id="add2"
|
||||
value="1234 North Avenue Luke Lane, South Bend, IN 360001"/>
|
||||
</div>
|
||||
|
||||
{/*<div className="form-row">*/}
|
||||
{/* <div className="form-group col-md-4">*/}
|
||||
{/* <label htmlFor="inputState3">City</label>*/}
|
||||
{/* <select id="inputState3" className="form-control">*/}
|
||||
{/* <option>Choose...</option>*/}
|
||||
{/* <option selected="">London</option>*/}
|
||||
{/* <option>Montreal</option>*/}
|
||||
{/* <option>Delhi</option>*/}
|
||||
{/* <option>Tokyo</option>*/}
|
||||
{/* </select>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="form-group col-md-4">*/}
|
||||
{/* <label htmlFor="inputState4">State</label>*/}
|
||||
{/* <select id="inputState4" className="form-control">*/}
|
||||
{/* <option>Choose...</option>*/}
|
||||
{/* <option selected="">England</option>*/}
|
||||
{/* <option>California</option>*/}
|
||||
{/* <option>Texas</option>*/}
|
||||
{/* <option>Scotland</option>*/}
|
||||
{/* </select>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="form-group col-md-4">*/}
|
||||
{/* <label htmlFor="inputZip">Zip</label>*/}
|
||||
{/* <input type="text" className="form-control" id="inputZip"*/}
|
||||
{/* value="EC1A 1BB" />*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
{/*<div className="form-group">*/}
|
||||
{/* <div className="form-check">*/}
|
||||
{/* <input className="form-check-input" type="checkbox"*/}
|
||||
{/* id="gridCheck" />*/}
|
||||
{/* <label className="form-check-label" htmlFor="gridCheck">*/}
|
||||
{/* I agree to receive email notification.*/}
|
||||
{/* </label>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
<div style={{textAlign: "right"}}>
|
||||
<button type="submit" className="btn btn-primary">Update Profile
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div className="col-xl-5 col-md-6 col-12 border-t border-right">
|
||||
<div className="page-account-form">
|
||||
<div className="form-titel border-bottom p-3">
|
||||
<h5 className="mb-0 py-2">Edit Your Personal Settings</h5>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<ProfileForm data={intialData.personal_data} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xl-4 col-md-6 border-t col-12">
|
||||
<div className="page-account-form">
|
||||
<div className="form-titel border-bottom p-3">
|
||||
<h5 className="mb-0 py-2">Your External Link</h5>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<form>
|
||||
<div className="form-group">
|
||||
<label htmlFor="fb">Facebook URL:</label>
|
||||
<input type="text" className="form-control" id="fb"
|
||||
value="https://www.facebook.com/"/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label htmlFor="tr">Twitter URL:</label>
|
||||
<input type="text" className="form-control" id="tr"
|
||||
value="https://twitter.com/"/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="br">Blogger URL:</label>
|
||||
<input type="text" className="form-control" id="br"
|
||||
value="https://www.blogger.com"/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="go">Google+ URL:</label>
|
||||
<input type="text" className="form-control" id="go"
|
||||
value="https://plus.google.com/discover"/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="li">LinkedIn URL:</label>
|
||||
<input type="text" className="form-control" id="li"
|
||||
value="https://in.linkedin.com/"/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="we">Website URL:</label>
|
||||
<input type="text" className="form-control" id="we"
|
||||
value="https://yourwebsite.com"/>
|
||||
</div>
|
||||
<div style={{textAlign: "right"}}>
|
||||
<button type="submit" className="btn btn-primary">Update Links
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<div className="col-xl-4 col-md-6 border-t col-12">
|
||||
<div className="page-account-form">
|
||||
<div className="form-titel border-bottom p-3">
|
||||
<h5 className="mb-0 py-2">Your External Link</h5>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<LinksForm data={intialData.external_links} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -197,8 +114,7 @@ export default function Settings() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import React from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
import TrafficChart from "./TrafficChart";
|
||||
|
||||
|
||||
export default function Traffic() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<BreadcrumbComBS title='Traffic' paths={['Dashboard', 'Traffic']}/>
|
||||
<div className="row">
|
||||
<div className="col-lg-4">
|
||||
<div className="card card-statistics" style={{minHeight: '350px', borderRadius: '10px', backgroundColor: 'aliceblue'}}>
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Site Traffic Monitoring</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-8">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Plot</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="apexchart-wrapper">
|
||||
<TrafficChart />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { useState } from "react";
|
||||
import ReactApexChart from "react-apexcharts";
|
||||
|
||||
const TrafficChart = () => {
|
||||
const [state, setState] = useState({
|
||||
|
||||
series: [
|
||||
{
|
||||
// name: "High - 2013",
|
||||
name: 'Professional Website',
|
||||
data: [28, 29, 33, 36, 32, 32, 33, 33, 36, 32, 32, 33]
|
||||
},
|
||||
{
|
||||
// name: "Low - 2013",
|
||||
name: 'Personal Website',
|
||||
data: [12, 11, 14, 18, 17, 13, 13, 14, 18, 17, 13, 13]
|
||||
},
|
||||
{
|
||||
// name: "Low - 2013",
|
||||
name: 'Personal Forum',
|
||||
data: [10, 11, 14, 19, 18, 23, 17, 14, 10, 17, 23, 10]
|
||||
},
|
||||
{
|
||||
// name: "High - 2013",
|
||||
name: 'Professional Forum',
|
||||
data: [20, 19, 30, 36, 30, 35, 33, 33, 36, 32, 32, 30]
|
||||
}
|
||||
],
|
||||
options: {
|
||||
chart: {
|
||||
height: 350,
|
||||
type: 'line',
|
||||
dropShadow: {
|
||||
enabled: true,
|
||||
color: '#000',
|
||||
top: 18,
|
||||
left: 7,
|
||||
blur: 10,
|
||||
opacity: 0.5
|
||||
},
|
||||
zoom: {
|
||||
enabled: false
|
||||
},
|
||||
toolbar: {
|
||||
show: false
|
||||
}
|
||||
},
|
||||
colors: ['#77B6EA', '#545454', '#F50898','#213ece'],
|
||||
dataLabels: {
|
||||
enabled: true,
|
||||
},
|
||||
stroke: {
|
||||
curve: 'smooth'
|
||||
},
|
||||
title: {
|
||||
text: 'Recent Sites Traffic',
|
||||
align: 'left'
|
||||
},
|
||||
grid: {
|
||||
borderColor: '#e7e7e7',
|
||||
row: {
|
||||
colors: ['#f3f3f3', 'transparent'], // takes an array which will be repeated on columns
|
||||
opacity: 0.5
|
||||
},
|
||||
},
|
||||
markers: {
|
||||
size: 1
|
||||
},
|
||||
xaxis: {
|
||||
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
|
||||
title: {
|
||||
text: 'Month'
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'Visits'
|
||||
},
|
||||
min: 5,
|
||||
max: 40
|
||||
},
|
||||
legend: {
|
||||
position: 'top',
|
||||
horizontalAlign: 'right',
|
||||
floating: true,
|
||||
offsetY: -25,
|
||||
offsetX: -5
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div id="chart">
|
||||
<ReactApexChart options={state.options} series={state.series} type="line" height={450} />
|
||||
</div>
|
||||
<div id="html-dist"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default TrafficChart
|
||||
@@ -2063,6 +2063,8 @@ ul.activity {
|
||||
.img-icon{
|
||||
width:60px;
|
||||
height:60px;
|
||||
min-width:60px;
|
||||
min-height:60px;
|
||||
border-radius:100px;
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
|
||||
@@ -3,6 +3,7 @@ const siteLinks = {
|
||||
help: '/help',
|
||||
home: '/',
|
||||
dash: '/dash',
|
||||
traffic: '/traffic',
|
||||
start: '/start',
|
||||
profile_complete: '/profile-complete',
|
||||
product: '/product/*',
|
||||
|
||||
@@ -10,6 +10,7 @@ const queryKeys = {
|
||||
myProductConfig: ['myproduct_config'],
|
||||
productTemplateData: ['product_template_data'],
|
||||
subscriptions: ['subscriptions'],
|
||||
profile_data: ['profile_data'],
|
||||
|
||||
dashboard: ['dashboard'],
|
||||
topBar: ['top-bar'],
|
||||
|
||||
@@ -26,8 +26,8 @@ const postAuxEnd = (path, postData, media=false) => {
|
||||
return axios.post(`${basePath}${path}`, postData).then(res => {
|
||||
return res
|
||||
}).catch(err => {
|
||||
// console.log('res', err.response.data)
|
||||
throw new Error(err.response.data.error_message);
|
||||
// throw new Error(err.response.data.error_message);
|
||||
throw new Error(err);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -76,6 +76,30 @@ export const topBar = (reqData) => {
|
||||
return postAuxEnd(`/panel/account/bar`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET PROFILE DATA
|
||||
export const profileDetails = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return postAuxEnd(`/panel/account/profile`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO UPDATE PROFILE
|
||||
export const updateProfile = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return postAuxEnd(`/panel/account/profile-update`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO UPDATE LINKS
|
||||
export const updateLinks = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return null //postAuxEnd(`/panel/account/links-update`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET PRODUCT BY ID
|
||||
export const MyProductData = (reqData) => {
|
||||
let postData = {
|
||||
@@ -99,7 +123,7 @@ export const getCalendarEvents = (reqData) => {
|
||||
return postAuxEnd(`/panel/account/calendar`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD PRODUCT DATA SECTION
|
||||
// FUNCTION TO GET CONTACT DATA
|
||||
export const contactData = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
@@ -107,6 +131,14 @@ export const contactData = (reqData) => {
|
||||
return postAuxEnd(`/panel/contacts`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET COMMENTS DATA
|
||||
export const commentsData = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return postAuxEnd(`/panel/comments`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD PRODUCT URL DATA SECTION
|
||||
export const productsURL = (reqData) => {
|
||||
let postData = {
|
||||
@@ -198,6 +230,12 @@ export const getProductTemplateData = (reqData) => {
|
||||
return postAuxEnd(`/panel/account/products/templates`, postData, false)
|
||||
}
|
||||
|
||||
export const getProductColorStyles = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return postAuxEnd(`/panel/account/products/color-styles`, postData, false)
|
||||
}
|
||||
// FUNCTION TO ACTIVATE TEMPLATE
|
||||
export const activateTemplate = (reqData) => {
|
||||
let postData = {
|
||||
@@ -206,6 +244,14 @@ export const activateTemplate = (reqData) => {
|
||||
return postAuxEnd(`/panel/account/template/activate`, postData, false)
|
||||
}
|
||||
|
||||
export const activateColorStyle = (reqData) => {
|
||||
let postData = {
|
||||
...reqData,
|
||||
}
|
||||
return postAuxEnd(`/panel/account/colorstyle/activate`, postData, false)
|
||||
}
|
||||
|
||||
|
||||
// FUNCTION TO GET PRODUCT SUBSCRIPTIONS
|
||||
export const completeProfile = (reqData) => {
|
||||
let postData = {
|
||||
@@ -230,6 +276,14 @@ export const getCommonPractice = (reqData) => {
|
||||
return postAuxEnd(`/panel/common/practice`, postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO SET EXTERNAL URL
|
||||
export const setExternalURL = (reqData) => {
|
||||
let postData = {
|
||||
...reqData
|
||||
}
|
||||
return postAuxEnd('/panel/myproduct/external-url', postData, false)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import React from 'react'
|
||||
import Traffic from "../component/traffic/Traffic";
|
||||
|
||||
export default function TrafficPage() {
|
||||
return (
|
||||
<Traffic />
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user