Merge branch 'master-bootstrap' of MERMS/MermsPanelReactJS into master
@@ -1,7 +1,10 @@
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
REACT_APP_NODE_ENV="development"
|
||||
REACT_APP_SOCKET_URL="https://dev-socket.mermsemr.com"
|
||||
REACT_APP_MAIN_API="https://dev-api.mermsemr.com"
|
||||
REACT_APP_MAIN_API="https://devapi.mermsemr.com"
|
||||
REACT_APP_MEDIA_SERVER="https://dev-media.mermsemr.com"
|
||||
REACT_APP_MAIN_SOCKET="https://dev-socket.mermsemr.com"
|
||||
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
SKIP_PREFLIGHT_CHECK=true
|
||||
REACT_APP_NODE_ENV="development"
|
||||
REACT_APP_SOCKET_URL="https://dev-socket.mermsemr.com"
|
||||
REACT_APP_MAIN_API="https://dev-api.mermsemr.com"
|
||||
REACT_APP_MAIN_API="https://devapi.mermsemr.com"
|
||||
REACT_APP_MEDIA_SERVER="https://dev-media.mermsemr.com"
|
||||
REACT_APP_MAIN_SOCKET="https://dev-socket.mermsemr.com"
|
||||
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
|
||||
@@ -3,3 +3,6 @@ REACT_APP_NODE_ENV="production"
|
||||
REACT_APP_SOCKET_URL="https://socket.mermsemr.com"
|
||||
REACT_APP_MAIN_API="https://api.mermsemr.com"
|
||||
REACT_APP_MEDIA_SERVER="https://media.mermsemr.com"
|
||||
|
||||
# Inactivity timeout/logout AT 10MINS
|
||||
REACT_APP_TIMEOUT=600000
|
||||
@@ -4,19 +4,29 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@reduxjs/toolkit": "^2.4.0",
|
||||
"@tanstack/react-query": "^5.62.3",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"apexcharts": "^4.1.0",
|
||||
"axios": "^1.7.9",
|
||||
"bootstrap": "^5.3.3",
|
||||
"dayjs": "^1.11.13",
|
||||
"formik": "^2.4.6",
|
||||
"react": "^18.3.1",
|
||||
"react-apexcharts": "^1.7.0",
|
||||
"react-big-calendar": "^1.17.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^7.0.2",
|
||||
"react-scripts": "5.0.1",
|
||||
"redux": "^5.0.1",
|
||||
"sass": "^1.82.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
"socket.io-client": "^4.8.1",
|
||||
"web-vitals": "^2.1.4",
|
||||
"yup": "^1.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start -e .env.development",
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -1,38 +1,11 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
.custom-bg {
|
||||
background-image: url('./assets/bg/bg_1.jpg') !important;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
.signup-bg {
|
||||
background-image: url('./assets/bg/signup_bg.jpg') !important;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
@@ -1,47 +1,24 @@
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
// import './App.css';
|
||||
import { QueryClientProvider, QueryClient } from '@tanstack/react-query'
|
||||
import AppRouters from './AppRouters';
|
||||
|
||||
import UserExist from './component/authorization/UserExist';
|
||||
import AuthLayout from './component/auth/AuthLayout';
|
||||
|
||||
import LoginPage from './views/LoginPage';
|
||||
import siteLinks from './links/siteLinks';
|
||||
import SignupPage from './views/SignupPage';
|
||||
import ForgetpwdPage from './views/ForgetpwdPage';
|
||||
import HomePage from './views/HomePage';
|
||||
import ReportsPage from './views/ReportsPage'
|
||||
import CommentsPage from './views/CommentsPage'
|
||||
import ContactsPage from './views/ContactsPage'
|
||||
import UserPage from './views/UserPage'
|
||||
import CalendarPage from './views/CalendarPage'
|
||||
import SettingsPage from './views/SettingsPage'
|
||||
import './App.css';
|
||||
|
||||
|
||||
function App() {
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
refetchOnWindowFocus: false,
|
||||
retry: 3,
|
||||
// refetchOnMount: false,
|
||||
staleTime: 3000
|
||||
},
|
||||
},
|
||||
})
|
||||
return (
|
||||
<div className="">
|
||||
<Routes>
|
||||
{/* auth routes wrapper */}
|
||||
<Route element={<AuthLayout />}>
|
||||
<Route path={siteLinks.home} element={<LoginPage />} />
|
||||
<Route path={siteLinks.login} element={<LoginPage />} />
|
||||
<Route path={siteLinks.signup} element={<SignupPage />} />
|
||||
<Route path={siteLinks.forgetpwd} element={<ForgetpwdPage />} />
|
||||
<Route path={siteLinks.error} element={<ForgetpwdPage />} />
|
||||
</Route>
|
||||
|
||||
{/* protected routes */}
|
||||
<Route element={<UserExist />}>
|
||||
<Route path={siteLinks.dash} element={<HomePage />} />
|
||||
<Route path={siteLinks.reports} element={<ReportsPage />} />
|
||||
<Route path={siteLinks.comments} element={<CommentsPage />} />
|
||||
<Route path={siteLinks.contacts} element={<ContactsPage />} />
|
||||
<Route path={siteLinks.user} element={<UserPage />} />
|
||||
<Route path={siteLinks.calendar} element={<CalendarPage />} />
|
||||
<Route path={siteLinks.settings} element={<SettingsPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AppRouters />
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
|
||||
import UserExist from './component/authorization/UserExist';
|
||||
import AuthLayout from './component/auth/AuthLayout';
|
||||
import siteLinks from './links/siteLinks';
|
||||
|
||||
import LoginPage from './views/LoginPage';
|
||||
import SignupPage from './views/SignupPage';
|
||||
import ForgetpwdPage from './views/ForgetpwdPage';
|
||||
import HomePage from './views/HomePage';
|
||||
import ReportsPage from './views/ReportsPage'
|
||||
import CommentsPage from './views/CommentsPage'
|
||||
import ContactsPage from './views/ContactsPage'
|
||||
import UserPage from './views/UserPage'
|
||||
import CalendarPage from './views/CalendarPage'
|
||||
import SettingsPage from './views/SettingsPage'
|
||||
import ProductPage from './views/ProductPage'
|
||||
import SocketIOContextProvider from './component/context/SocketIOContext';
|
||||
import CSignupPage from './views/CSignupPage';
|
||||
|
||||
function AppRouters() {
|
||||
return (
|
||||
<div className="">
|
||||
<Routes>
|
||||
{/* auth routes wrapper */}
|
||||
<Route element={<AuthLayout />}>
|
||||
<Route path={siteLinks.home} element={<LoginPage />} />
|
||||
<Route path={siteLinks.login} element={<LoginPage />} />
|
||||
<Route path={siteLinks.signup} element={<SignupPage />} />
|
||||
<Route path={siteLinks.forgetpwd} element={<ForgetpwdPage />} />
|
||||
<Route path={siteLinks.csignup} element={<CSignupPage />} />
|
||||
<Route path={siteLinks.error} element={<LoginPage />} />
|
||||
</Route>
|
||||
|
||||
{/* protected routes */}
|
||||
<Route element={<SocketIOContextProvider />}>
|
||||
<Route element={<UserExist />}>
|
||||
<Route path={siteLinks.dash} element={<HomePage />} />
|
||||
<Route path={siteLinks.product} element={<ProductPage />} />
|
||||
<Route path={siteLinks.reports} element={<ReportsPage />} />
|
||||
<Route path={siteLinks.comments} element={<CommentsPage />} />
|
||||
<Route path={siteLinks.contacts} element={<ContactsPage />} />
|
||||
<Route path={siteLinks.user} element={<UserPage />} />
|
||||
<Route path={siteLinks.calendar} element={<CalendarPage />} />
|
||||
<Route path={siteLinks.settings} element={<SettingsPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppRouters;
|
||||
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 78 KiB |
@@ -0,0 +1,174 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
// import LoginImg from '../../assets/bg/login.svg'
|
||||
|
||||
import { Link, useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||
import siteLinks from '../../links/siteLinks'
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { signUpUser } from '../../services/services';
|
||||
|
||||
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"),
|
||||
password: Yup.string().required("Password is required"),
|
||||
confirmpassword: Yup.string().required("Confirm Password is required").oneOf([Yup.ref('password')], 'Passwords must match')
|
||||
// lastname: Yup.string().required("Lastname is required"),
|
||||
// isChecked: Yup.bool().oneOf([true], "Please accept the terms & policy"), // use bool instead of boolean
|
||||
})
|
||||
|
||||
const initialValues = {
|
||||
email: '',
|
||||
password: '',
|
||||
confirmpassword: '',
|
||||
// lastname: '',
|
||||
// isChecked: false,
|
||||
};
|
||||
|
||||
export default function CSignup() {
|
||||
|
||||
const {jwt} = useParams()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return signUpUser(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
console.log('res', res)
|
||||
}
|
||||
})
|
||||
|
||||
const CSignUp = (values) => {
|
||||
// helpers.resetForm()
|
||||
// console.log('values', values, helpers)
|
||||
// mutation.mutate(values)
|
||||
console.log('values', values)
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(!jwt){
|
||||
return navigate(siteLinks.login, {replace: true})
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
<div className="app-wrap">
|
||||
<div className="app-contant">
|
||||
<div className="bg-white custom-bg">
|
||||
<div className="container-fluid p-0">
|
||||
<div className="row no-gutters justify-content-center">
|
||||
<div className="col-sm-6 col-lg-5 col-xxl-3 align-self-center order-2 order-sm-1 h-100-vh">
|
||||
<div className="mt-5 d-flex">
|
||||
<div className="bg-white register p-5">
|
||||
<h1 className="mb-2">MERMS Panel</h1>
|
||||
<p>Welcome, Enter your password.</p>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={CSignUp}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='mt-2 mt-sm-5'>
|
||||
<div className="row">
|
||||
{!mutation.isSuccess ?
|
||||
<>
|
||||
{/* <div className="col-12 col-sm-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">
|
||||
<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.password && props.touched.password) && 'text-danger'}`}>Password*</label>
|
||||
<input type="password" name='password' className="form-control" placeholder="password" value={props.values.password} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label`}>Confirm Password* <span className={`${(props.errors.confirmpassword && props.touched.confirmpassword) && 'text-danger'}`}>{(props.errors.confirmpassword && props.touched.confirmpassword) && props.errors.confirmpassword}</span></label>
|
||||
<input type="password" name='confirmpassword' className="form-control" placeholder="confirmpassword" value={props.values.confirmpassword} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <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>
|
||||
</>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3 text-end">
|
||||
<button type='submit' className="btn btn-primary text-uppercase">{mutation.isPending ? 'loading...' : 'Continue'}</button>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<div className='col-12'>
|
||||
<div className="rounded-2 d-flex flex-column justify-content-between align-items-center" style={{height: '200px', backgroundColor: '#F2FAF7'}}>
|
||||
<h4 className='p-4 text-black'>Check your email to continue.</h4>
|
||||
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3 text-center">
|
||||
<Link to={siteLinks.login} className='text-primary' style={{color: '#6FCAEF'}}>Need help with logging in or signing up?</Link>
|
||||
</div>
|
||||
|
||||
<div className="col-12 mt-3 text-center">
|
||||
{/* <p>Already have an account ?<Link to={siteLinks.login}> Sign In</Link></p> */}
|
||||
<p>Ready our Privacy Statement</p>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="custom-bg col-sm-6 col-xxl-9 col-lg-7 b-gradient o-hidden order-1 order-sm-2">
|
||||
<div className="row align-items-center h-100">
|
||||
<div className="col-7 mx-auto ">
|
||||
<img className="img-fluid" src={LoginImg} alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,23 +1,43 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import LoginImg from '../../assets/bg/login.svg'
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
// import LoginImg from '../../assets/bg/login.svg'
|
||||
|
||||
import MainLoaderBS from '../loaders/MainLoaderBS'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { Link } from 'react-router-dom'
|
||||
import siteLinks from '../../links/siteLinks'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { recoverPWD } from '../../services/services';
|
||||
|
||||
const validationSchema = Yup.object().shape({
|
||||
username: 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"),
|
||||
})
|
||||
|
||||
const initialValues = {
|
||||
username: ''
|
||||
};
|
||||
|
||||
export default function Forgetpwd2() {
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return recoverPWD(fields)
|
||||
},
|
||||
// onSuccess: (res) => {
|
||||
// console.log('res', res)
|
||||
// }
|
||||
})
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(()=>{
|
||||
const timer = setTimeout(()=>{
|
||||
setLoading(false)
|
||||
},1000)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
},[])
|
||||
const recoverPWDSubmit = (values) => {
|
||||
mutation.mutate(values)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
@@ -31,29 +51,57 @@ export default function Forgetpwd2() {
|
||||
<div className="login p-50">
|
||||
<h1 className="mb-2">Recover Password</h1>
|
||||
<p>Please enter your email.</p>
|
||||
<form className="mt-3 mt-sm-5">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className="control-label">Email*</label>
|
||||
<input type="text" className="form-control" placeholder="Email" />
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={recoverPWDSubmit}
|
||||
>
|
||||
{(props) => {
|
||||
return (
|
||||
<Form className='mt-2 mt-sm-5'>
|
||||
<div className="row">
|
||||
{!mutation.isSuccess ?
|
||||
<>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.username && props.touched.username) && 'text-danger'}`}>Email*</label>
|
||||
<input type="email" name='username' className="form-control" placeholder="Email" value={props.values.username} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div>
|
||||
{mutation.error &&
|
||||
<>
|
||||
<div className="col-12 mt-3">
|
||||
<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...' : 'Send'}</button>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<div className='col-12'>
|
||||
<div className="rounded-2 d-flex flex-column justify-content-between align-items-center" style={{height: '200px', backgroundColor: '#F2FAF7'}}>
|
||||
<h4 className='p-4 text-black'>Check your email to continue password reset.</h4>
|
||||
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 mt-3">
|
||||
<button type='button' onClick={()=>{navigate(siteLinks.dash)}} className="btn btn-primary text-uppercase">Send</button>
|
||||
</div>
|
||||
<div className="col-12 mt-3">
|
||||
<p>Go <Link to={siteLinks.home}> Back</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
<div className="col-12 mt-3">
|
||||
<p>Go <Link to={siteLinks.home}> Back</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-9 col-lg-7 bg-gradient o-hidden order-1 order-sm-2">
|
||||
<div className="custom-bg col-sm-6 col-xxl-9 col-lg-7 b-gradient o-hidden order-1 order-sm-2">
|
||||
<div className="row align-items-center h-100">
|
||||
<div className="col-7 mx-auto ">
|
||||
<img className="img-fluid" src={LoginImg} alt="" />
|
||||
{/* <img className="img-fluid" src={LoginImg} alt="" /> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,66 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import LoginImg from '../../assets/bg/login.svg'
|
||||
import React, { useState } from 'react'
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
import { useDispatch } from 'react-redux'
|
||||
|
||||
// import LoginImg from '../../assets/bg/login.svg'
|
||||
|
||||
import MainLoaderBS from '../loaders/MainLoaderBS'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
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'
|
||||
|
||||
export default function Login() {
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(()=>{
|
||||
const timer = setTimeout(()=>{
|
||||
setLoading(false)
|
||||
},1000)
|
||||
const [fields, setFields] = useState({
|
||||
username: localStorage.getItem('username') || '',
|
||||
password: '',
|
||||
remember: localStorage.getItem('username') ? true : false
|
||||
})
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
},[])
|
||||
const handleChange = ({target:{name, value}}) => {
|
||||
if(name == 'remember'){
|
||||
return setFields(prev => ({...prev, remember:!prev.remember}))
|
||||
}
|
||||
setFields(prev => ({...prev, [name]:value}))
|
||||
}
|
||||
|
||||
const login = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
if(!fields.username || !fields.password){
|
||||
throw new Error('Please provide all fields marked *')
|
||||
}
|
||||
rememberMe(fields.remember) // FUNCTION TO SAVE USERNAME OF THE USER TO LOCAL STORAGE
|
||||
return loginUser(fields)
|
||||
},
|
||||
onError: (error) => {
|
||||
console.log(error)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
const {token, room} = res?.data?.data
|
||||
if(token){
|
||||
localStorage.setItem('token', token)
|
||||
localStorage.setItem('room', room)
|
||||
// const data = {token}
|
||||
// dispatch(updateUserDetails({ ...data }));
|
||||
navigate('/dash') // later add redux to dispatch state
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const rememberMe = (checked) => {
|
||||
if(checked){
|
||||
localStorage.setItem('username', fields.username)
|
||||
}else{
|
||||
localStorage.removeItem('username')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
@@ -35,42 +78,72 @@ export default function Login() {
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className="control-label">User Name*</label>
|
||||
<input type="text" className="form-control" placeholder="Username" />
|
||||
<label className="control-label text-black fw-bold">User Name*</label>
|
||||
<input 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">Password*</label>
|
||||
<input type="password" className="form-control" placeholder="Password" />
|
||||
<label className="control-label text-black fw-bold">Password*</label>
|
||||
<input name='password' value={fields.password} onChange={handleChange} type="password" className="form-control" placeholder="Password" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="d-block d-sm-flex align-items-center">
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="checkbox" id="gridCheck" />
|
||||
<label className="form-check-label" htmlFor="gridCheck">
|
||||
<input className="form-check-input" type="checkbox" id="gridCheck" name='remember' checked={fields.remember} onChange={handleChange} disabled={!fields.username ? true : false} />
|
||||
<label className="form-check-label text-black" htmlFor="gridCheck">
|
||||
Remember Me
|
||||
</label>
|
||||
</div>
|
||||
<Link to={siteLinks.forgetpwd} className="ml-auto">Forgot Password ?</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 mt-3">
|
||||
<button type='button' onClick={()=>{navigate(siteLinks.dash)}} className="btn btn-primary text-uppercase">Sign In</button>
|
||||
{login.error &&
|
||||
<>
|
||||
<div className="col-12">
|
||||
<p className='text-danger'>{login.error.message}</p>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
<div className="col-12 mt-3 text-end">
|
||||
<button type='button' onClick={()=>{login.mutate(fields)}} className="btn btn-primary text-uppercase">{login.isPending ? 'loading...' : 'Sign In'}</button>
|
||||
</div>
|
||||
<div className="col-12 mt-3">
|
||||
<p>Don't have an account ?<Link to={siteLinks.signup}> Sign Up</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div className="row" style={{marginTop: '20px'}}>
|
||||
<div className="col-6">
|
||||
<div className="app-store-icons-wrap text-center">
|
||||
<a className="icon google"
|
||||
href='#'
|
||||
// href="https://play.google.com/store/apps/details?id=com.mermsemr.providers" target="_blank"
|
||||
>
|
||||
<img src={IOSDownload} className='w-100 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='#'
|
||||
// href="https://play.google.com/store/apps/details?id=com.mermsemr.providers" target="_blank"
|
||||
>
|
||||
<img src={GoogleDownload} className='w-100 h-auto' alt='IOS Download' />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-9 col-lg-7 bg-gradient o-hidden order-1 order-sm-2">
|
||||
<div className="custom-bg col-sm-6 col-xxl-9 col-lg-7 b-gradient o-hidden order-1 order-sm-2">
|
||||
<div className="row align-items-center h-100">
|
||||
<div className="col-7 mx-auto ">
|
||||
<img className="img-fluid" src={LoginImg} alt="" />
|
||||
{/* <img className="img-fluid" src={LoginImg} alt="" /> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,23 +1,56 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import LoginImg from '../../assets/bg/login.svg'
|
||||
import React, { useState } from 'react'
|
||||
import { Form, Formik } from "formik";
|
||||
import * as Yup from "yup";
|
||||
|
||||
import MainLoaderBS from '../loaders/MainLoaderBS'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
// import LoginImg from '../../assets/bg/login.svg'
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
import siteLinks from '../../links/siteLinks'
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { signUpUser } from '../../services/services';
|
||||
|
||||
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"),
|
||||
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 = {
|
||||
email: '',
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
isChecked: false,
|
||||
// username: '',
|
||||
// password: ''
|
||||
};
|
||||
|
||||
export default function Signup2() {
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const mutation = useMutation({
|
||||
mutationFn: (fields) => {
|
||||
return signUpUser(fields)
|
||||
},
|
||||
onSuccess: (res) => {
|
||||
console.log('res', res)
|
||||
}
|
||||
})
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(()=>{
|
||||
const timer = setTimeout(()=>{
|
||||
setLoading(false)
|
||||
},1000)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
},[])
|
||||
const signUp = (values) => {
|
||||
// helpers.resetForm()
|
||||
// console.log('values', values, helpers)
|
||||
mutation.mutate(values)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
@@ -26,66 +59,98 @@ export default function Signup2() {
|
||||
<div className="bg-white">
|
||||
<div className="container-fluid p-0">
|
||||
<div className="row no-gutters">
|
||||
<div class="col-sm-6 col-lg-5 col-xxl-3 align-self-center order-2 order-sm-1">
|
||||
<div class="d-flex align-items-center h-100-vh">
|
||||
<div class="register p-5">
|
||||
<h1 class="mb-2">MERMS Panel</h1>
|
||||
<div className="col-sm-6 col-lg-5 col-xxl-3 align-self-center order-2 order-sm-1">
|
||||
<div className="d-flex align-items-center h-100-vh">
|
||||
<div className="register p-5">
|
||||
<h1 className="mb-2">MERMS Panel</h1>
|
||||
<p>Welcome, Please create your account.</p>
|
||||
<form class="mt-2 mt-sm-5">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label">First Name*</label>
|
||||
<input type="text" class="form-control" placeholder="First Name" />
|
||||
<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-sm-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-sm-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} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form-group">
|
||||
<label className={`text-black fw-bold control-label ${(props.errors.password && props.touched.password) && 'text-danger'}`}>Password*</label>
|
||||
<input type="password" name='password' className="form-control" placeholder="Password" value={props.values.password} onChange={props.handleChange} />
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="col-12">
|
||||
<div className="form-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>
|
||||
</>
|
||||
}
|
||||
|
||||
<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={{height: '200px', backgroundColor: '#F2FAF7'}}>
|
||||
<h4 className='p-4 text-black'>Check your email to continue.</h4>
|
||||
<Link to={siteLinks.login} className='p-2 text-primary' style={{color: '#6FCAEF'}}>Home</Link>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className="col-12 mt-3">
|
||||
<p>Already have an account ?<Link to={siteLinks.login}> Sign In</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Last Name*</label>
|
||||
<input type="text" class="form-control" placeholder="Last Name" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Email*</label>
|
||||
<input type="email" class="form-control" placeholder="Email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Username*</label>
|
||||
<input type="text" class="form-control" placeholder="Username" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Password*</label>
|
||||
<input type="password" class="form-control" placeholder="Password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="gridCheck" />
|
||||
<label class="form-check-label" for="gridCheck">
|
||||
I accept terms & policy
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mt-3">
|
||||
<button type='button' onClick={()=>navigate(siteLinks.dash)} class="btn btn-primary text-uppercase">Sign up</button>
|
||||
</div>
|
||||
<div class="col-12 mt-3">
|
||||
<p>Already have an account ?<Link to={siteLinks.login}> Sign In</Link></p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}}
|
||||
</Formik>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-9 col-lg-7 bg-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="" />
|
||||
{/* <img className="img-fluid" src={LoginImg} alt="" /> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,103 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Outlet } from 'react-router-dom'
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Outlet, useNavigate } from 'react-router-dom'
|
||||
import { updateUserDetails } from "../../store/UserDetails";
|
||||
import MainLoaderBS from '../loaders/MainLoaderBS'
|
||||
import Layout from '../layout/Layout'
|
||||
import siteLinks from '../../links/siteLinks'
|
||||
|
||||
import debounceFunction from '../../utils/debounceFunction'
|
||||
import { accountDashboard } from '../../services/services';
|
||||
import { SocketContextValues } from '../context/SocketIOContext';
|
||||
|
||||
|
||||
export default function UserExist() {
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const {joinRoom} = SocketContextValues() // Destructures values from socket context
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const [lastActivityTime, setLastActivityTime] = useState(Date.now()); // HOLDS THE INITIAL TIME USER LOGS IN
|
||||
|
||||
const { userDetails: { lastname }} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
|
||||
|
||||
let loggedIn = lastname ? true : false; // variable to determine if user is logged in
|
||||
// console.log('loggedIn', loggedIn)
|
||||
|
||||
// Function to log the user out
|
||||
const logoutUser = () => {
|
||||
localStorage.clear()
|
||||
navigate(siteLinks.login)
|
||||
window.location.reload()
|
||||
};
|
||||
|
||||
// Function to reset the activity time
|
||||
const resetTimer = () => {
|
||||
debounceFunction(setLastActivityTime(Date.now()), 1000)
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
const timer = setTimeout(()=>{
|
||||
setLoading(false)
|
||||
},1000)
|
||||
if(Date.now() - Number(lastActivityTime) >= Number(process.env.REACT_APP_TIMEOUT)){
|
||||
logoutUser()
|
||||
}
|
||||
}, Number(process.env.REACT_APP_TIMEOUT))
|
||||
|
||||
// Listen for activity events
|
||||
const events = ['mousemove', 'keydown', 'click', 'scroll', 'touchstart'];
|
||||
|
||||
// Adding event listeners
|
||||
events.forEach(event => {
|
||||
window.addEventListener(event, resetTimer);
|
||||
});
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer)
|
||||
events.forEach(event => {
|
||||
window.removeEventListener(event, resetTimer);
|
||||
})
|
||||
}
|
||||
},[lastActivityTime])
|
||||
|
||||
useEffect(()=>{
|
||||
accountDashboard().then(res => {
|
||||
const {dash_data} = res?.data
|
||||
setLoading(false)
|
||||
dispatch(updateUserDetails({ ...dash_data }));
|
||||
}).catch(err => {
|
||||
navigate(siteLinks.login)
|
||||
setLoading(false)
|
||||
})
|
||||
},[])
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
|
||||
// useEffect(()=>{
|
||||
// let token = localStorage.getItem('token')
|
||||
// const timer = setTimeout(()=>{
|
||||
// if(token && loggedIn){
|
||||
// setLoading(false)
|
||||
// }else if(token && !loggedIn){
|
||||
// const data = {token}
|
||||
// dispatch(updateUserDetails({ ...data }));
|
||||
// setLoading(false)
|
||||
// // dispatch(updateUserDetails({ ...res.data }));
|
||||
// }else{
|
||||
// navigate('auth/login')
|
||||
// }
|
||||
// },1000)
|
||||
|
||||
// return () => clearTimeout(timer)
|
||||
// },[])
|
||||
|
||||
useEffect(()=>{
|
||||
if(localStorage.getItem('room')){
|
||||
joinRoom(localStorage.getItem('room'));
|
||||
joinRoom("merms_global_events"); // global room for all
|
||||
}
|
||||
},[])
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,14 +1,112 @@
|
||||
import React from "react";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
import EventCalendar from "./EventCalendar";
|
||||
|
||||
|
||||
export default function Calendar(){
|
||||
|
||||
const [draggedEvent, setDraggedEvent] = useState('undroppable')
|
||||
const handleDragStart = useCallback((event) => setDraggedEvent(event), [])
|
||||
|
||||
// const dummyEvents = [
|
||||
// {id: '1', title: 'Family Vacation', color: 'fc-event-primary', start: new Date('2024-12-18'), end: new Date('2024-12-18'), isAllDay: false, resource: ''},
|
||||
// {id: '2', title: 'Meeting In Office', color: 'fc-event-warning', start: new Date('2024-12-19'), end: new Date('2024-12-19'), isAllDay: false, resource: ''},
|
||||
// {id: '3', title: 'Client Call', color: 'fc-event-danger', start: new Date('2024-12-20'), end: new Date('2024-12-20'), isAllDay: false, resource: ''},
|
||||
// {id: '4', title: 'Interview', color: 'fc-event-success', start: new Date('2024-12-21'), end: new Date('2024-12-21'), isAllDay: false, resource: ''}
|
||||
// ]
|
||||
const dummyEvents = [
|
||||
{id: '1', title: 'Family Vacation', color: 'fc-event-primary', isAllDay: false},
|
||||
{id: '2', title: 'Meeting In Office', color: 'fc-event-warning', isAllDay: false},
|
||||
{id: '3', title: 'Client Call', color: 'fc-event-danger', isAllDay: false},
|
||||
{id: '4', title: 'Interview', color: 'fc-event-success', isAllDay: false}
|
||||
]
|
||||
|
||||
return(
|
||||
<>
|
||||
<BreadcrumbComBS title='Calendar' paths={['Dashboard', 'Calendar']} />
|
||||
<div className="row">
|
||||
<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>
|
||||
<div className="col-lg-12">
|
||||
<div className="card card-statistics">
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Event Calendar</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-xl-3">
|
||||
<div id="external-events">
|
||||
<button className="btn btn-primary btn-block" data-bs-toggle="modal" data-bs-target="#eventModal">
|
||||
Add New Event
|
||||
</button>
|
||||
<p className="mt-3">
|
||||
Drag and drop your event or click in the calendar.
|
||||
</p>
|
||||
{dummyEvents.map((item, index) => (
|
||||
<div key={index} className={`fc-event ${item.color}`} data-color={`${item.color}`}
|
||||
draggable="true"
|
||||
onDragStart={() =>
|
||||
handleDragStart({...item})
|
||||
}
|
||||
>
|
||||
<span></span> {item.title}
|
||||
</div>
|
||||
))}
|
||||
<div className="form-check">
|
||||
<input className="form-check-input" type="checkbox" value=""
|
||||
id="defaultCheck1" />
|
||||
<label className="form-check-label" htmlFor="defaultCheck1">
|
||||
Remove After Drop
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xl-9">
|
||||
<div className="event-calendar">
|
||||
<EventCalendar draggedEvent={draggedEvent} setDraggedEvent={setDraggedEvent} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Event Modal */}
|
||||
<div className="modal fade" id="eventModal" tabIndex="-1" role="dialog">
|
||||
<div className="modal-dialog modal-dialog-centered" role="document">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title" id="verticalCenterTitle">Add New Event</h5>
|
||||
<button type="button" className="close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form>
|
||||
<div className="form-group">
|
||||
<label>Event Name</label>
|
||||
<input type="email" className="form-control" id="eventname" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>Choose Event Color</label>
|
||||
<select className="form-control">
|
||||
<option>Primary</option>
|
||||
<option>Warning</option>
|
||||
<option>Success</option>
|
||||
<option>Danger</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" className="btn btn-success">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { Calendar, dayjsLocalizer } from 'react-big-calendar'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
|
||||
|
||||
|
||||
|
||||
const localizer = dayjsLocalizer(dayjs)
|
||||
|
||||
const DnDCalendar = withDragAndDrop(Calendar)
|
||||
|
||||
export default function EventCalendar({draggedEvent, setDraggedEvent}) {
|
||||
const myEventsList = []
|
||||
const [myEvents, setMyEvents] = useState(myEventsList)
|
||||
|
||||
const moveEvent = useCallback(
|
||||
({ event, start, end, isAllDay: droppedOnAllDaySlot = false }) => {
|
||||
// const { isAllDay } = event
|
||||
// if (!allDay && droppedOnAllDaySlot) {
|
||||
// event.allDay = true
|
||||
// }
|
||||
// if (allDay && !droppedOnAllDaySlot) {
|
||||
// event.allDay = false;
|
||||
// }
|
||||
|
||||
setMyEvents((prev) => {
|
||||
const existing = prev.find((ev) => ev.id === event.id) ?? {}
|
||||
const filtered = prev.filter((ev) => ev.id !== event.id)
|
||||
return [...filtered, { ...existing, start, end, allDay: event.allDay }]
|
||||
})
|
||||
},
|
||||
[setMyEvents]
|
||||
)
|
||||
const [displayDragItemInCell, setDisplayDragItemInCell] = useState(true)
|
||||
|
||||
|
||||
const dragFromOutsideItem = useCallback(() => draggedEvent === 'undroppable' ? null : draggedEvent, [draggedEvent])
|
||||
|
||||
const customOnDragOverFromOutside = useCallback(
|
||||
(dragEvent) => {
|
||||
// check for undroppable is specific to this example
|
||||
// and not part of API. This just demonstrates that
|
||||
// onDragOver can optionally be passed to conditionally
|
||||
// allow draggable items to be dropped on cal, based on
|
||||
// whether event.preventDefault is called
|
||||
if (draggedEvent !== 'undroppable') {
|
||||
console.log('preventDefault')
|
||||
dragEvent.preventDefault()
|
||||
}
|
||||
},
|
||||
[draggedEvent]
|
||||
)
|
||||
|
||||
|
||||
const eventPropGetter = useCallback(
|
||||
(event) => ({
|
||||
...(event.isDraggable
|
||||
? { className: 'isDraggable' }
|
||||
: { className: 'nonDraggable' }),
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const newEvent = useCallback(
|
||||
(event) => {
|
||||
setMyEvents((prev) => {
|
||||
const idList = prev.map((item) => item.id)
|
||||
const newId = Math.max(...idList) + 1
|
||||
// return [...prev, { ...event, id: newId }]
|
||||
return [...prev, { ...event}]
|
||||
})
|
||||
},
|
||||
[setMyEvents]
|
||||
)
|
||||
|
||||
const onDropFromOutside = useCallback(
|
||||
({ start, end, allDay: isAllDay }) => {
|
||||
if (draggedEvent === 'undroppable') {
|
||||
setDraggedEvent(null)
|
||||
return
|
||||
}
|
||||
|
||||
const { title, id } = draggedEvent
|
||||
const event = {
|
||||
title: title,
|
||||
start,
|
||||
end,
|
||||
isAllDay,
|
||||
id
|
||||
}
|
||||
setDraggedEvent(null)
|
||||
newEvent(event)
|
||||
},
|
||||
[draggedEvent, setDraggedEvent, newEvent]
|
||||
)
|
||||
|
||||
const resizeEvent = useCallback(
|
||||
({ event, start, end }) => {
|
||||
setMyEvents((prev) => {
|
||||
const existing = prev.find((ev) => ev.id === event.id) ?? {}
|
||||
const filtered = prev.filter((ev) => ev.id !== event.id)
|
||||
return [...filtered, { ...existing, start, end }]
|
||||
})
|
||||
},
|
||||
[setMyEvents]
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='w-100'>
|
||||
<DnDCalendar
|
||||
dragFromOutsideItem={
|
||||
displayDragItemInCell ? dragFromOutsideItem : null
|
||||
}
|
||||
eventPropGetter={eventPropGetter}
|
||||
// draggableAccessor="isDraggable"
|
||||
localizer={localizer}
|
||||
events={myEvents}
|
||||
startAccessor="start"
|
||||
endAccessor="end"
|
||||
style={{ height: 500 }}
|
||||
// onEventResize={resizeEvent}
|
||||
resizable
|
||||
onEventDrop={moveEvent}
|
||||
onDropFromOutside={onDropFromOutside}
|
||||
// onDragOverFromOutside={customOnDragOverFromOutside}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
|
||||
import getImage from "../../utils/getImage";
|
||||
|
||||
export default function Comments(){
|
||||
|
||||
@@ -8,7 +8,364 @@ export default function Comments(){
|
||||
<>
|
||||
<BreadcrumbComBS title='Comments' paths={['Dashboard', 'Comments']} />
|
||||
<div className="row">
|
||||
<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>
|
||||
{/*<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">className= <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+</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>
|
||||
</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>
|
||||
</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>
|
||||
</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/02.jpg")} className="img-fluid" alt="user" />
|
||||
</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></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>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
|
||||
import getImage from "../../utils/getImage";
|
||||
|
||||
export default function Contacts(){
|
||||
|
||||
@@ -8,7 +8,355 @@ export default function Contacts(){
|
||||
<>
|
||||
<BreadcrumbComBS title='Contacts' paths={['Dashboard', 'Contacts']} />
|
||||
<div className="row">
|
||||
<div className="vh-100 col-12 flex align-items-center">Coming Soon</div>
|
||||
{/*<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">className= <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+</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>
|
||||
</span>
|
||||
<span>
|
||||
<span>Replied 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>*/}
|
||||
</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>
|
||||
</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/02.jpg")} className="img-fluid" alt="user" />
|
||||
</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></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="assets/img/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="assets/img/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="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>
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { io } from "socket.io-client";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
import { socketEmitEvents, socketOnEvents } from "./socketEvents";
|
||||
// import io from "socket.io-client";
|
||||
|
||||
// import { tableReload } from "../../store/TableReloads";
|
||||
// import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
|
||||
let SocketIOContext = createContext({})
|
||||
|
||||
export default function SocketIOContextProvider({children}) {
|
||||
const queryClient = useQueryClient()
|
||||
// const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER UID, to determine if user is active
|
||||
|
||||
// const dispatch = useDispatch()
|
||||
|
||||
const socket = io.connect(process.env.REACT_APP_SOCKET_URL);
|
||||
|
||||
// // Messages States
|
||||
// const [message, setMessage] = useState("");
|
||||
const [socketMsgReceived, setSocketMsgReceived] = useState("");
|
||||
|
||||
const joinRoom = (room) => {
|
||||
if (room !== "") {
|
||||
return socket.emit("join_room", room);
|
||||
}
|
||||
return
|
||||
};
|
||||
|
||||
const sendMessage = (eventType, message, room) => {
|
||||
if(message && room){
|
||||
socket.emit(eventType, { message, room });
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
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)
|
||||
queryClient.refetchQueries({
|
||||
queryKey: [...queryKeys.recentAction],
|
||||
// type: 'active',
|
||||
// exact: true,
|
||||
})
|
||||
});
|
||||
|
||||
// client-side
|
||||
socket.on("connect", () => {
|
||||
console.log(socket.id);
|
||||
});
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
console.log(socket.id);
|
||||
});
|
||||
}, [socket]);
|
||||
|
||||
let values = {
|
||||
socket,
|
||||
sendMessage,
|
||||
socketMsgReceived,
|
||||
setSocketMsgReceived,
|
||||
joinRoom,
|
||||
}
|
||||
|
||||
return (
|
||||
<SocketIOContext.Provider value={values}>
|
||||
<Outlet />
|
||||
</SocketIOContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const SocketContextValues = () => {
|
||||
return useContext(SocketIOContext)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export const socketEmitEvents = {
|
||||
send_message: 'send_message'
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const socketOnEvents = {
|
||||
receive_message: 'receive_message'
|
||||
}
|
||||
@@ -1,9 +1,19 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
|
||||
import RecentActions from "./RecentActions";
|
||||
import Products from "./Products";
|
||||
import TopBar from "./TopBar";
|
||||
import ProductsURL from "./ProductsURL";
|
||||
import { SocketContextValues } from "../context/SocketIOContext";
|
||||
|
||||
export default function HomeSections(){
|
||||
|
||||
const {sendMessage} = SocketContextValues() // Destructures values from socket context
|
||||
|
||||
// useEffect(()=>{
|
||||
// sendMessage('Hello socket', '2020aklksod')
|
||||
// },[])
|
||||
|
||||
return <>
|
||||
{/* <div className="row">
|
||||
<div className="col-md-12 m-b-30">
|
||||
@@ -29,424 +39,50 @@ export default function HomeSections(){
|
||||
</div> */}
|
||||
<BreadcrumbComBS title='Home' paths={['Dashboard', 'Home']} />
|
||||
<div className="row">
|
||||
<div className="col-sm-6 col-xxl-3">
|
||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
||||
<div className="card-body p-0">
|
||||
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
||||
<div className="w-100">
|
||||
<div className="row p-3">
|
||||
<div className="col">
|
||||
<h3 className="mb-0">$65,456</h3>
|
||||
<small className="d-block">Last 6 months</small>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<h5 className="text-muted mb-0">Revenue</h5>
|
||||
<strong className="text-danger m-t-5"><i
|
||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> N/A</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommercedemo3" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-3">
|
||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
||||
<div className="card-body p-0">
|
||||
<div className="d-flex ecommerce-contant-text m-b-0 h-100">
|
||||
<div className="w-100">
|
||||
<div className="row p-3">
|
||||
<div className="col">
|
||||
<h3 className="mb-0">52%</h3>
|
||||
<small className="d-block">Past 12 hours</small>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<h5 className="text-muted mb-0">Conversion Rate</h5>
|
||||
<strong className="text-primary m-t-5"><i
|
||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> 5.35%</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommercedemo1" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-3">
|
||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
||||
<div className="card-body p-0">
|
||||
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
||||
<div className="w-100">
|
||||
<div className="w-100">
|
||||
<div className="row p-3">
|
||||
<div className="col">
|
||||
<h3 className="mb-0">605</h3>
|
||||
<small className="d-block">Last 90 days</small>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<h5 className="text-muted mb-0">Transactions</h5>
|
||||
<strong className="text-orange m-t-5"><i
|
||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> 4.65%</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommercedemo2" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-sm-6 col-xxl-3">
|
||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
||||
<div className="card-body p-0">
|
||||
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
||||
<div className="w-100">
|
||||
<div className="row p-3">
|
||||
<div className="col">
|
||||
<h3 className="mb-0">5,687</h3>
|
||||
<small className="d-block">Last 3 months</small>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<h5 className="text-muted mb-0">Purchases</h5>
|
||||
<strong className="text-success m-t-5"><i
|
||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> 9.89%</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommercedemo4" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<TopBar />
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xxl-6 m-b-30">
|
||||
<div className="card card-statistics h-100 mb-0">
|
||||
<div className="card-header">
|
||||
<h4 className="card-title">My Products</h4>
|
||||
</div>
|
||||
<div className="card-body pb-0">
|
||||
<div className="row m-b-20">
|
||||
<div className="col-xxs-6 col-xl-4 col-xxl-4 mb-2 mb-xxl-0">
|
||||
<div className="d-flex align-items-center">
|
||||
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
|
||||
<i className="fa fa-cart-plus text-primary"></i>
|
||||
</div>
|
||||
<div className="report-details">
|
||||
<p>Annual Sales</p>
|
||||
<h3>15,236</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xxs-6 col-md-4 col-xxl-4 mb-2 mb-xxl-0">
|
||||
<div className="d-flex align-items-center">
|
||||
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
|
||||
<i className="fa fa-dollar text-primary"></i>
|
||||
</div>
|
||||
<div className="report-details">
|
||||
<p>Annual Revenue</p>
|
||||
<h3>$40,516</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommerce5" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Products />
|
||||
</div>
|
||||
<div className="col-xxl-6 m-b-30">
|
||||
<div className="card card-statistics h-100 mb-0">
|
||||
<div className="card-header d-sm-flex justify-content-between align-items-center py-3">
|
||||
<div className="card-heading mb-3 mb-sm-0">
|
||||
<h4 className="card-title">Recent Actions</h4>
|
||||
</div>
|
||||
<div className="dropdown">
|
||||
{/*<input type="text" className="form-control form-control-sm" placeholder="Search Invoice"/>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card-body scrollbar scroll_dark" style={{maxHeight: '420px'}}>
|
||||
<div className="d-xxs-flex align-items-center">
|
||||
<div className="total-sales">
|
||||
<p>Last Update</p>
|
||||
<h1>10-10-2021 10 AM</h1>
|
||||
</div>
|
||||
<div className="mb-3 mb-sm-0 ml-auto">
|
||||
{/*<button className="btn btn-primary btn-xs">View All Invoices</button>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-none d-sm-flex progress m-t-20 m-b-0" style={{height: '5px'}}>
|
||||
<div className="progress-bar bg-primary" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-warning" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-info" role="progressbar" style={{width: '25%'}} aria-valuenow="20"
|
||||
aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-success" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<div className="row no-gutters">
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Overdue</p>
|
||||
<h4>$1596</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Outstanding</p>
|
||||
<h4>$2586</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Open</p>
|
||||
<h4>$5678</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Paid</p>
|
||||
<h4>$2458</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-responsive m-t-20">
|
||||
<table id="datatable-buttons" className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No.</th>
|
||||
<th>Name</th>
|
||||
<th>Date</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-muted">
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Smith Drake</td>
|
||||
<td>27/3/2014</td>
|
||||
<td>$1,00,000</td>
|
||||
<td>
|
||||
<label className="badge mb-0 badge-primary-inverse"> Overdue</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Martha Doe</td>
|
||||
<td>28/3/2015</td>
|
||||
<td>$70,000</td>
|
||||
<td>
|
||||
<label className="badge mb-0 badge-warning-inverse
|
||||
"> Outstanding</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Fenish Paul</td>
|
||||
<td>24/3/2015</td>
|
||||
<td>$60,000</td>
|
||||
<td>
|
||||
<label className="badge mb-0 badge-info-inverse
|
||||
"> Open</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Albom Mitch</td>
|
||||
<td>29/3/2016</td>
|
||||
<td>$60,000</td>
|
||||
<td>
|
||||
<label className="badge mb-0 badge-success-inverse
|
||||
"> Paid</label>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<RecentActions />
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-xxl-8 m-b-30">
|
||||
<div className="card card-statistics h-100 mb-0">
|
||||
<div className="card-header d-flex align-items-center justify-content-between">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Top selling products</h4>
|
||||
</div>
|
||||
<div className="dropdown">
|
||||
{/*<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="datatable-wrapper table-responsive">
|
||||
<table id="datatable" className="table table-borderless table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>In stock</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Cold Shoulder Bling Dress</td>
|
||||
<td>$65.342</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '80%'}}
|
||||
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-success-inverse">Active</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>PlayStation 4 Pro 1TB Console</td>
|
||||
<td>$47.655</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '36%'}} aria-valuenow="36" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-success-inverse">Active</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Extra Fine Wool Jumpers</td>
|
||||
<td>$56.479</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '60%'}} aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-danger-inverse">Canceled</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Long Sleeve Bow Top</td>
|
||||
<td>$04.786</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '50%'}}
|
||||
aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-success-inverse">Active</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Shine Stripe Long Sleeve Ruffle</td>
|
||||
<td>$23.456</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '75%'}}
|
||||
aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-success-inverse">Active</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>Long Sleeve Micro Thermal Shirt</td>
|
||||
<td>$65.598</td>
|
||||
<td>
|
||||
<div className="progress my-3" style={{height: '3px'}}>
|
||||
<div className="progress-bar" role="progressbar" style={{width: '90%'}}
|
||||
aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><span className="badge badge-info-inverse">info</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a><a
|
||||
href=""><i className="fe fe-trash-2"></i></a></td>
|
||||
</tr>
|
||||
<ProductsURL />
|
||||
|
||||
|
||||
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>In stock</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-xxl-4 m-b-30">
|
||||
<div className="card card-statistics h-100 mb-0">
|
||||
<div className="card card-statistics h-100 mb-0 panel_round_c3">
|
||||
<div className="card-header d-flex justify-content-between">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Lifetime sales</h4>
|
||||
</div>
|
||||
<div className="dropdown">
|
||||
<a className="p-2" href="#!" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
<i className="fe fe-circle"></i>
|
||||
</a>
|
||||
<div className="dropdown-menu custom-dropdown dropdown-menu-right p-4">
|
||||
<h6 className="mb-1">Action</h6>
|
||||
<a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-o pr-2"></i>View
|
||||
reports</a>
|
||||
<a className="dropdown-item" href="#!"><i className="fa-fw fa fa-edit pr-2"></i>Edit reports</a>
|
||||
<a className="dropdown-item" href="#!"><i className="fa-fw fa fa-bar-chart-o pr-2"></i>Statistics</a>
|
||||
<h6 className="mb-1 mt-3">Export</h6>
|
||||
<a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-pdf-o pr-2"></i>Export
|
||||
to PDF</a>
|
||||
<a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-excel-o pr-2"></i>Export
|
||||
to CSV</a>
|
||||
</div>
|
||||
<h4 className="card-title">Payments</h4>
|
||||
</div>
|
||||
{/*<div className="dropdown">*/}
|
||||
{/* <a className="p-2" href="#!" data-toggle="dropdown" aria-haspopup="true"*/}
|
||||
{/* aria-expanded="false">*/}
|
||||
{/* <i className="fe fe-circle"></i>*/}
|
||||
{/* </a>*/}
|
||||
{/* <div className="dropdown-menu custom-dropdown dropdown-menu-right p-4">*/}
|
||||
{/* <h6 className="mb-1">Action</h6>*/}
|
||||
{/* <a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-o pr-2"></i>View*/}
|
||||
{/* reports</a>*/}
|
||||
{/* <a className="dropdown-item" href="#!"><i className="fa-fw fa fa-edit pr-2"></i>Edit reports</a>*/}
|
||||
{/* <a className="dropdown-item" href="#!"><i className="fa-fw fa fa-bar-chart-o pr-2"></i>Statistics</a>*/}
|
||||
{/* <h6 className="mb-1 mt-3">Export</h6>*/}
|
||||
{/* <a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-pdf-o pr-2"></i>Export*/}
|
||||
{/* to PDF</a>*/}
|
||||
{/* <a className="dropdown-item" href="#!"><i className="fa-fw fa fa-file-excel-o pr-2"></i>Export*/}
|
||||
{/* to CSV</a>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<h5>We only started collecting data from February 2019 </h5>
|
||||
<p>Questions about the Net Earnings number? <a
|
||||
className="btn btn-square btn-inverse-success btn-xs ml-1" href="#">Click here</a></p>
|
||||
{/*<h5>We only started collecting data from February 2019 </h5>*/}
|
||||
{/*<p>Questions about the Net Earnings number? <a*/}
|
||||
{/* className="btn btn-square btn-inverse-success btn-xs ml-1" href="#">Click here</a></p>*/}
|
||||
<div className="row mt-4">
|
||||
<div className="col-lg-8">
|
||||
<div className="morris-wrapper">
|
||||
<div id="morrisecommerce1" style={{height: '260px'}}></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-4 mt-4">
|
||||
<div className="mb-3">
|
||||
<h3 className="mb-0">680</h3>
|
||||
<p className="mb-0 text-info">Total sales</p>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<h3 className="mb-0">800</h3>
|
||||
<p className="mb-0 text-primary">Open campaign</p>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<h3 className="mb-0">500</h3>
|
||||
<p className="mb-0">Daily sales</p>
|
||||
</div>
|
||||
</div>
|
||||
.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import React from 'react'
|
||||
import { productData } from '../../services/services'
|
||||
import queryKeys from '../../services/queryKeys'
|
||||
import productPath from "../../utils/productpath";
|
||||
import { Link } from 'react-router-dom';
|
||||
export default function Products() {
|
||||
|
||||
const {data, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.product,
|
||||
queryFn: () => productData()
|
||||
})
|
||||
|
||||
const products = data?.data?.products_data?.products
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="card card-statistics h-100 mb-0 panel_round_c1">
|
||||
<div className="card-header">
|
||||
<h4 className="card-title">My Products</h4>
|
||||
</div>
|
||||
<div className="card-body pb-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 m-b-20">
|
||||
{products && products.map((product, index) => (
|
||||
<div key={product.uid+index} className="col-xxs-6 col-xl-4 col-xxl-6 mb-2 mb-xxl-0 ">
|
||||
<Link to={productPath(product?.uid)} >
|
||||
<div className="d-flex align-items-center extraProductCard">
|
||||
<div className="icon-container img-icon m-r-20 bg-light-gray rounded">
|
||||
<i className="fa fa-cart-plus text-primary"></i>
|
||||
</div>
|
||||
<div className="report-details">
|
||||
<p>{product?.status}</p>
|
||||
<h4>{product?.description}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
</div>
|
||||
))}
|
||||
{/*<div style={{backgroundColor: 'green'}} className="col-xxs-6 col-md-4 col-xxl-6 mb-2 mb-xxl-0">*/}
|
||||
{/* <div className="d-flex align-items-center">*/}
|
||||
{/* <div className="icon-container img-icon m-r-20 bg-light-gray rounded">*/}
|
||||
{/* <i className="fa fa-dollar text-primary"></i>*/}
|
||||
{/* </div>*/}
|
||||
{/* <div className="report-details">*/}
|
||||
{/* <p>Annual Revenue</p>*/}
|
||||
{/* <h3>$40,516</h3>*/}
|
||||
{/* </div>*/}
|
||||
{/* </div>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
}
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommerce5" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
import React from 'react'
|
||||
import { productsURL } from '../../services/services'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import queryKeys from '../../services/queryKeys'
|
||||
|
||||
export default function ProductsURL() {
|
||||
|
||||
const {data:data, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.product_url,
|
||||
queryFn: () => productsURL()
|
||||
})
|
||||
|
||||
const urlData = data?.data?.url_data?.url
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="col-xxl-8 m-b-30">
|
||||
<div className="card card-statistics h-100 mb-0">
|
||||
<div className="card-header d-flex align-items-center justify-content-between">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">My Product URLs</h4>
|
||||
</div>
|
||||
<div className="dropdown">
|
||||
{/*<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="datatable-wrapper table-responsive">
|
||||
{isFetching ?
|
||||
<>
|
||||
<div className="col-12">
|
||||
<div className="p-4">
|
||||
<p className='text-mute'>Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
: isError ?
|
||||
<div className="col-12">
|
||||
<div className="p-4">
|
||||
<p className='text-danger'>{error.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<table id="datatable" className="table table-borderless table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{width: '30px'}}>#</th>
|
||||
<th>Description</th>
|
||||
|
||||
<th style={{width: '100px'}}>Status</th>
|
||||
<th style={{width: '40px'}}>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{urlData && urlData.map((item, index) => {
|
||||
let statusColor = item?.status == 'Active' ? 'badge-success-inverse' : item?.status == 'Updating' ? 'badge-success-inverse' : item?.status == 'Refreshing' ? 'badge-danger-inverse' : 'badge-info-inverse'
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{Number(item?.no) + Number(index)}</td>
|
||||
<td>{item?.description} - <a href={item?.url} target='_blank'>{item?.url}</a></td>
|
||||
|
||||
<td><span className={`badge ${statusColor}`}>{item?.status}</span></td>
|
||||
<td><a className="mr-3" href=""><i className="fe fe-edit"></i></a></td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>In stock</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
import React from 'react'
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { recentActions } from "../../services/services";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
|
||||
export default function RecentActions() {
|
||||
|
||||
const {data:dataAction, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.recentAction,
|
||||
queryFn: () => recentActions()
|
||||
})
|
||||
|
||||
const actionData = dataAction?.data?.action_data
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="card card-statistics h-100 mb-0 panel_round_c2" style={{minHeight: '460px'}}>
|
||||
<div className="card-header">
|
||||
<div className="card-heading">
|
||||
<h4 className="card-title">Recent Actions</h4>
|
||||
</div>
|
||||
{/* <div className="dropdown">
|
||||
<input type="text" className="form-control form-control-sm" placeholder="Search Invoice"/>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="card-body scrollbar scroll_dark" style={{maxHeight: '450px'}}>
|
||||
{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="d-xxs-flex align-items-center">
|
||||
<div className="total-sales">
|
||||
<p>Last Update</p>
|
||||
<h3>{dataAction?.data?.action_data?.last_update}</h3>
|
||||
</div>
|
||||
<div className="mb-3 mb-sm-0 ml-auto">
|
||||
{/*<button className="btn btn-primary btn-xs">View All Invoices</button>*/}
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-none d-sm-flex progress m-t-20 m-b-0" style={{height: '5px'}}>
|
||||
<div className="progress-bar bg-primary" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-warning" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-info" role="progressbar" style={{width: '25%'}} aria-valuenow="20"
|
||||
aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div className="progress-bar bg-success" role="progressbar" style={{width: '25%'}}
|
||||
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<div className="row no-gutters">
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Initial</p>
|
||||
<h4>{actionData?.initial}</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Processing</p>
|
||||
<h4>{actionData?.processing}</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Verifying</p>
|
||||
<h4>{actionData?.verifying}</h4>
|
||||
</div>
|
||||
<div className="col-6 col-xxs-3 ">
|
||||
<p>Completed</p>
|
||||
<h4>{actionData?.completed}</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div className="table-responsive m-t-20">
|
||||
<table id="datatable-buttons" className="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{width: '30px'}}>#.</th>
|
||||
<th>Description</th>
|
||||
<th style={{width: '100px'}}>Date</th>
|
||||
<th style={{width: '100px'}}>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="text-muted">
|
||||
{actionData && actionData?.actions.map((action, index) => {
|
||||
let bgColor = action?.status == 'completed' ? 'badge-success-inverse' : action?.status == 'verifying' ? 'badge-info-inverse' : action?.status == 'processing' ? 'badge-warning-inverse' : 'badge-primary-inverse'
|
||||
return (
|
||||
<tr key={index}>
|
||||
<td>{action?.no}</td>
|
||||
<td>{action?.description}</td>
|
||||
<td>{action?.date}</td>
|
||||
<td>
|
||||
<label className={`badge mb-0 ${bgColor}`}>{action?.status}</label>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import React from 'react'
|
||||
import { topBar } from '../../services/services'
|
||||
import queryKeys from '../../services/queryKeys'
|
||||
|
||||
export default function TopBar() {
|
||||
|
||||
const {data, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.topBar,
|
||||
queryFn: () => topBar()
|
||||
})
|
||||
|
||||
const topData = data?.data?.bar_data?.top_bar
|
||||
console.log('TOP', topData)
|
||||
|
||||
return (
|
||||
<>
|
||||
{isFetching ?
|
||||
<>
|
||||
<div className="col-12">
|
||||
<div className="card p-4">
|
||||
<p className='text-mute'>Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
: isError ?
|
||||
<div className="col-12">
|
||||
<div className="card p-4">
|
||||
<p className='text-danger'>{error.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
:
|
||||
<>
|
||||
{topData && topData?.map((item, index)=>{
|
||||
let textColor = item?.description == 'Contacts' ? 'text-danger' : item?.description == 'Site Traffic' ? 'text-primary' : item?.description == 'Appointments' ? 'text-orange' : 'text-success'
|
||||
return (
|
||||
<div key={item.id + index} className="col-sm-6 col-xxl-3">
|
||||
<div className="card card-statistics ecommerce-contant overflow-h">
|
||||
<div className="card-body p-0">
|
||||
<div className="d-flex m-b-0 ecommerce-contant-text h-100">
|
||||
<div className="w-100">
|
||||
<div className="row p-3">
|
||||
<div className="col">
|
||||
<h3 className="mb-0">{item?.value || 0}</h3>
|
||||
<small className="d-block">{item?.data_span}</small>
|
||||
</div>
|
||||
<div className="col text-right">
|
||||
<h5 className="text-muted mb-0">{item?.description}</h5>
|
||||
<strong className={`${textColor} m-t-5`}><i
|
||||
className="zmdi zmdi-long-arrow-up font-weight-bold"></i> N/A</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="apexchart-wrapper">
|
||||
<div id="ecommercedemo3" className="chart-fit"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -1,46 +1,74 @@
|
||||
import React from "react";
|
||||
import getImage from "../../../utils/getImage";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
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 toggleSidebar = (e) => {
|
||||
e.preventDefault()
|
||||
document.body.classList.toggle('sidebar-toggled')
|
||||
}
|
||||
|
||||
const removeSidebar = (e) => {
|
||||
e.preventDefault()
|
||||
document.body.classList.remove('sidebar-toggled')
|
||||
}
|
||||
|
||||
// const toggleSidebarMini = (e) => {
|
||||
// e.preventDefault()
|
||||
// }
|
||||
|
||||
const navigate = useNavigate()
|
||||
|
||||
const logout = () => {
|
||||
localStorage.clear()
|
||||
navigate(siteLinks.login, {replace: true})
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="app-header top-bar">
|
||||
<nav className="navbar navbar-expand-md">
|
||||
<div className="navbar-header d-flex align-items-center">
|
||||
<a href="#" className="mobile-toggle"><i className="ti ti-align-right"></i></a>
|
||||
<a href="#" onClick={toggleSidebar} className="mobile-toggle"><i className="ti ti-align-right"></i></a>
|
||||
<a className="navbar-brand" href="/dash">
|
||||
<img src={getImage('logo-light.png')} className="img-fluid logo-desktop" alt="logo"/>
|
||||
<img src={getImage('logo-icon.png')} className="img-fluid logo-mobile" alt="logo"/>
|
||||
</a>
|
||||
</div>
|
||||
<button className="navbar-toggler" type="button" data-toggle="collapse"
|
||||
data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
|
||||
<button onClick={removeSidebar} className="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
|
||||
aria-label="Toggle navigation">
|
||||
<i className="ti ti-align-left"></i>
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<div className="navigation d-flex">
|
||||
<div className="navigation d-flex align-items-center">
|
||||
<ul className="navbar-nav nav-left">
|
||||
<li className="nav-item">
|
||||
<h4 className="text-info pt-1">{userDetails?.account_name}</h4>
|
||||
{/* <li className="nav-item">
|
||||
<a href="#" className="nav-link sidebar-toggle">
|
||||
<i className="ti ti-align-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</li> */}
|
||||
|
||||
<li className="nav-item full-screen d-none d-lg-block" id="btnFullscreen">
|
||||
{/* <li className="nav-item full-screen d-none d-lg-block" id="btnFullscreen">
|
||||
<a href="#" className="nav-link expand">
|
||||
<i className="icon-size-fullscreen"></i>
|
||||
</a>
|
||||
</li>
|
||||
</li> */}
|
||||
</ul>
|
||||
|
||||
{/* ul className="navbar-nav nav-right ml-auto dropdown" */}
|
||||
<ul className="navbar-nav nav-right ml-auto">
|
||||
{/* <li className="nav-item dropdown">
|
||||
<a className="nav-link dropdown-toggle" href="#" id="navbarDropdown2" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<a href="#" className="nav-link dropdown-toggle" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i className="ti ti-email"></i>
|
||||
</a>
|
||||
<div className="dropdown-menu extended animated fadeIn" aria-labelledby="navbarDropdown">
|
||||
<div className="dropdown-menu extended animated fadeIn" aria-labelledby="dropdownMenuLink">
|
||||
<ul>
|
||||
<li className="dropdown-header bg-gradient p-4 text-white text-left">Messages
|
||||
<label className="label label-info label-round">6</label>
|
||||
@@ -134,16 +162,16 @@ export default function UserHeader(){
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li className="nav-item dropdown">
|
||||
<a className="nav-link dropdown-toggle" href="#" id="navbarDropdown3" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
</li> */}
|
||||
{/* <li className="nav-item dropdown">
|
||||
<a href="#" className="nav-link dropdown-toggle" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i className="fe fe-bell"></i>
|
||||
<span className="notify">
|
||||
<span className="blink"></span>
|
||||
<span className="dot"></span>
|
||||
</span>
|
||||
</a>
|
||||
<div className="dropdown-menu extended animated fadeIn" aria-labelledby="navbarDropdown">
|
||||
<div className="dropdown-menu extended animated fadeIn" aria-labelledby="dropdownMenuLink">
|
||||
<ul>
|
||||
<li className="dropdown-header bg-gradient p-4 text-white text-left">Notifications
|
||||
<a href="#" className="float-right btn btn-square btn-inverse-light btn-xs m-0">
|
||||
@@ -234,8 +262,8 @@ export default function UserHeader(){
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
</li> */}
|
||||
{/* <li className="nav-item">
|
||||
<a className="nav-link search" href="#">
|
||||
<i className="ti ti-search"></i>
|
||||
</a>
|
||||
@@ -254,8 +282,7 @@ export default function UserHeader(){
|
||||
</div>
|
||||
</div>
|
||||
</li> */}
|
||||
|
||||
<li className="nav-item user-profile dropdown">
|
||||
<li className="nav-item user-profile">
|
||||
<a href="#" className="nav-link dropdown-toggle" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<img src={getImage('avtar/02.jpg')} alt="avtar-img" />
|
||||
<span className="bg-success user-status"></span>
|
||||
@@ -264,10 +291,10 @@ export default function UserHeader(){
|
||||
<div className="bg-gradient px-4 py-3">
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<div className="mr-1">
|
||||
<h4 className="text-white mb-0">Alice Williams</h4>
|
||||
<small className="text-white">Henry@example.com</small>
|
||||
<h5 className="text-white mb-0">{userDetails?.firstname} {userDetails?.lastname}</h5>
|
||||
<small className="text-white">{userDetails.email}</small>
|
||||
</div>
|
||||
<a href="#" className="text-white font-20 tooltip-wrapper" data-toggle="tooltip"
|
||||
<a href="#" onClick={logout} className="text-white font-20 tooltip-wrapper" data-toggle="tooltip"
|
||||
data-placement="top" title="" data-original-title="Logout"> <i
|
||||
className="zmdi zmdi-power"></i></a>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
import React from 'react'
|
||||
import { Link, useLocation } from 'react-router-dom'
|
||||
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
||||
import siteLinks from '../../../links/siteLinks'
|
||||
import { IoIosArrowDown } from 'react-icons/io'
|
||||
export default function UserMenu() {
|
||||
|
||||
const {pathname} = useLocation()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const logout = () => {
|
||||
localStorage.clear()
|
||||
navigate(siteLinks.login, {replace: true})
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sidebar-nav scrollbar scroll_dark">
|
||||
@@ -48,7 +56,7 @@ export default function UserMenu() {
|
||||
|
||||
<li className="sidebar-banner p-4 bg-gradient text-center m-3 d-block rounded">
|
||||
<h5 className="text-white mb-1">MERMS Panel</h5>
|
||||
<Link className="btn btn-square btn-inverse-light btn-xs d-inline-block mt-2 mb-0" to={siteLinks.login}> Log Out</Link>
|
||||
<Link className="btn btn-square btn-inverse-light btn-xs d-inline-block mt-2 mb-0" to='' onClick={logout}> Log Out</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from "react";
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import BreadcrumbComBS from "../breadcrumb/BreadcrumbComBS";
|
||||
// import getImage from "../../utils/getImage";
|
||||
import ProductStart from "./ProductStart";
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import {MyProductData, productData} from "../../services/services";
|
||||
import queryKeys from "../../services/queryKeys";
|
||||
|
||||
export default function ProductFactory(){
|
||||
const location = useLocation();
|
||||
const pathname = location.pathname;
|
||||
|
||||
|
||||
// Split the pathname by '/' and get the last element
|
||||
const lastPart = pathname.split('/').pop();
|
||||
console.log(lastPart)
|
||||
|
||||
const {data, isFetching, isError, error} = useQuery({
|
||||
queryKey: queryKeys.product,
|
||||
queryFn: () => MyProductData(lastPart)
|
||||
})
|
||||
|
||||
const myproduct_data = data?.data?.myproduct_data
|
||||
|
||||
const product_name = myproduct_data?.product_name;
|
||||
|
||||
return(
|
||||
<>
|
||||
<BreadcrumbComBS title={product_name} paths={['Dashboard', 'Product']} />
|
||||
<div className="row">
|
||||
{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>
|
||||
<ProductStart productData={myproduct_data} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import React, { useRef } from "react";
|
||||
import getImage from "../../utils/getImage";
|
||||
import { Modal } from "bootstrap";
|
||||
export default function ProductStart(props){
|
||||
|
||||
console.log(props)
|
||||
const productBanner = "product/"+props.productData.banner;
|
||||
const productTitle = props.productData.title;
|
||||
const productDescription = props.productData.description;
|
||||
const promotion_text = props.productData.promotion_text;
|
||||
|
||||
const modalRef = useRef()
|
||||
|
||||
const hideModal = () => {
|
||||
// modalRef.current.hide()
|
||||
|
||||
// document.body.classList.remove('modal-open')
|
||||
// const modal = new Modal(document.querySelector('.modal'))
|
||||
// modal.hide()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row">
|
||||
<div className="col-md-9">
|
||||
<div className="card card-statistics ">
|
||||
<img className="card-img-top" src={getImage(productBanner)} alt="Card image cap" />
|
||||
<div className="card-body">
|
||||
<h4 className="card-title">{productTitle}</h4>
|
||||
<p className="card-text">{productDescription}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-3">
|
||||
<div className="card card-statistics mb-30 panel_round_c3">
|
||||
{/*<img className="card-img-top" src={getImage('widget/01.jpg')} alt="Card image cap" />*/}
|
||||
<div className="card-body">
|
||||
<h4 className="card-title">Subscription</h4>
|
||||
<p className="card-text">Start with your goals in mind and then work possible.ith yand Goals. If the plan doesn’t support the vision then change it! </p>
|
||||
</div>
|
||||
<ul className="list-group list-group-flush">
|
||||
<li className="list-group-item"><h4>{promotion_text}</h4></li>
|
||||
<li className="list-group-item">90 days free and 3.95/Month</li>
|
||||
<li className="list-group-item"></li>
|
||||
</ul>
|
||||
{/*<div className="card-body">*/}
|
||||
{/* <a href="javascript:void(0)" className="card-link">Card link</a>*/}
|
||||
{/* <a href="javascript:void(0)" className="card-link">Another link</a>*/}
|
||||
{/*</div>*/}
|
||||
<div className="subscribe-box">
|
||||
<button className="btn btn-primary mt-2" data-bs-toggle="modal" data-bs-target="#verticalCenter">Start Product</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Vertical Center Modal */}
|
||||
<div ref={modalRef} className="modal fade" id="verticalCenter" 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" id="verticalCenterTitle">Modal title</h5>
|
||||
<button type="button" className="close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis
|
||||
in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at
|
||||
eros. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus
|
||||
sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean lacinia
|
||||
bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque
|
||||
nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor
|
||||
fringilla. Cras mattis consectetur purus sit amet fermentum. Cras justo odio,
|
||||
dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur
|
||||
ac, vestibulum at eros. Praesent commodo cursus magna, vel scelerisque nisl consectetur
|
||||
et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Aenean
|
||||
lacinia bibendum nulla sed consectetur.
|
||||
</p>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-danger" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" className="btn btn-success" onClick={hideModal}>Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* END of Vertical Center Modal */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -324,19 +324,19 @@
|
||||
|
||||
@include mobile-landscape {
|
||||
margin:0 !important;
|
||||
justify-content: space-between;
|
||||
justify-content: end;
|
||||
padding:0 30px;
|
||||
width: 100%;;
|
||||
}
|
||||
@include mobile-portrait-sm {
|
||||
margin:0 !important;
|
||||
justify-content: space-between;
|
||||
justify-content: end;
|
||||
padding:0 30px;
|
||||
width: 100%;;
|
||||
}
|
||||
@include mobile-portrait-xs {
|
||||
margin:0 !important;
|
||||
justify-content: space-between;
|
||||
justify-content: end;
|
||||
padding:0 30px;
|
||||
width: 100%;;
|
||||
}
|
||||
@@ -588,13 +588,18 @@
|
||||
left: 0px;
|
||||
}
|
||||
}
|
||||
.show {
|
||||
.dropdown-menu{
|
||||
margin-top: 0;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.show + .dropdown-menu{
|
||||
margin-top: 0;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
// .show {
|
||||
// .dropdown-menu{
|
||||
// margin-top: 0;
|
||||
// visibility: visible;
|
||||
// opacity: 1;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
.nav-item.dropdown, .nav-item.dropup {
|
||||
@include mobile-landscape {
|
||||
|
||||
@@ -84,5 +84,68 @@
|
||||
@import "pages/coming-soon";
|
||||
|
||||
|
||||
// THIS IMPORTS ARE FOR THE CALENDAR PACKAGE - PLEASE DO NOT REMOVE
|
||||
$today-highlight-bg: #fcf8e3;
|
||||
// $btn-color: #fff;
|
||||
$btn-bg: #8e54e9;
|
||||
$btn-border: #8e54e9;
|
||||
$event-padding: 10px;
|
||||
|
||||
@import 'react-big-calendar/lib/sass/styles';
|
||||
@import 'react-big-calendar/lib/addons/dragAndDrop/styles'; // if using DnD
|
||||
|
||||
.extraProductCard{
|
||||
background-color: aliceblue;
|
||||
border-radius: 5px;
|
||||
margin: 2px;
|
||||
}
|
||||
.subscribe-box{
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.panel_round_c1{
|
||||
background-color: #e6f5f4;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.panel_round_c2{
|
||||
background-color: #e3dfef;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.panel_round_c3{
|
||||
background-color: #fcfaf1;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* CALENDER STYLE HERE */
|
||||
// .rbc-today{
|
||||
// background-color: '#fcf8e3' !important;
|
||||
// }
|
||||
.rbc-toolbar button {
|
||||
background: #eceef3;
|
||||
border: none;
|
||||
color: #a6a9b7 !important;
|
||||
text-transform: capitalize;
|
||||
box-shadow: none!important;
|
||||
text-shadow: none!important;
|
||||
border-radius: 3px!important;
|
||||
margin: 0 3px!important;
|
||||
padding: 6px 12px!important;
|
||||
height: auto!important;
|
||||
}
|
||||
.rbc-toolbar-label{
|
||||
color: black !important;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
// .rbc-month-view{
|
||||
// border: .5px solid #e8edf1!important;
|
||||
// }
|
||||
.rbc-toolbar button.rbc-active, .rbc-toolbar button:active, .rbc-toolbar button:hover{
|
||||
color: #fff!important;
|
||||
}
|
||||
/* END OF CALENDER STYLE */
|
||||
@@ -1,8 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
// import './index.css';
|
||||
import App from './App';
|
||||
import { Provider } from 'react-redux';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import store from './store/store'
|
||||
|
||||
import App from './App';
|
||||
//import reportWebVitals from './reportWebVitals';
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import 'bootstrap/dist/js/bootstrap.min.js'
|
||||
@@ -14,7 +17,9 @@ const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ const siteLinks = {
|
||||
error: '*',
|
||||
home: '/',
|
||||
dash: '/dash',
|
||||
product: '/product/*',
|
||||
contacts: '/contacts',
|
||||
comments: '/comments',
|
||||
reports: '/reports',
|
||||
@@ -10,7 +11,8 @@ const siteLinks = {
|
||||
settings: '/settings',
|
||||
login: '/auth/login',
|
||||
signup: '/auth/signup',
|
||||
forgetpwd: '/auth/forgetpwd'
|
||||
forgetpwd: '/auth/forgetpwd',
|
||||
csignup: '/csignup/:jwt'
|
||||
}
|
||||
|
||||
export default siteLinks
|
||||
@@ -0,0 +1,9 @@
|
||||
const queryKeys = {
|
||||
dashboard: ['dashboard'],
|
||||
topBar: ['top-bar'],
|
||||
recentAction: ['recent-action'],
|
||||
product: ['product-data'],
|
||||
product_url: ['product_url']
|
||||
}
|
||||
|
||||
export default queryKeys
|
||||
@@ -0,0 +1,99 @@
|
||||
import axios from "axios"
|
||||
|
||||
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
config.headers = {
|
||||
// Accept: "application/json",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
// "Access-Control-Expose-Headers": "Access-Control-Allow-Origin",
|
||||
// "Access-Control-Allow-Headers": "Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token",
|
||||
// "Content-Type": "application/json;charset=UTF-8",
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`
|
||||
};
|
||||
// config.headers['Authorization'] = `Bearer ${localStorage.getItem('token')}`;
|
||||
// config.baseURL = process.env.REACT_APP_MAIN_API
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
const postAuxEnd = (path, postData, media=false) => {
|
||||
const basePath = media ? process.env.REACT_APP_MAIN_API : process.env.REACT_APP_MAIN_API
|
||||
return axios.post(`${basePath}${path}`, postData).then(res => {
|
||||
return res
|
||||
}).catch(err => {
|
||||
throw new Error(err.response.data.message);
|
||||
})
|
||||
}
|
||||
|
||||
const getAuxEnd = (path, reqData= null) => {
|
||||
const basePath = process.env.REACT_APP_MAIN_API
|
||||
return axios.get(`${basePath}${path}`,{ params: reqData }).then(res => {
|
||||
return res
|
||||
// localStorage.clear();
|
||||
// window.location.href = `/login?sessionExpired=true`;
|
||||
}).catch(err => {
|
||||
throw new Error(err);
|
||||
// throw new Error(err.response.data.message);
|
||||
// return err
|
||||
})
|
||||
}
|
||||
|
||||
// FUNCTION TO LOGIN USER IN
|
||||
export const loginUser = (reqData) => {
|
||||
let postData = {
|
||||
...reqData
|
||||
}
|
||||
return postAuxEnd('/panel/auth/login', postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO REGISTER USER
|
||||
export const signUpUser = (reqData) => {
|
||||
let postData = {
|
||||
...reqData
|
||||
}
|
||||
return postAuxEnd('/panel/auth/register', postData, false)
|
||||
}
|
||||
|
||||
|
||||
// FUNCTION TO RESET USER PASSWORD
|
||||
export const recoverPWD = (reqData) => {
|
||||
let postData = {
|
||||
...reqData
|
||||
}
|
||||
return postAuxEnd('/panel/auth/reset', postData, false)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD DATA
|
||||
export const accountDashboard = () => {
|
||||
return getAuxEnd(`/panel/account/dash`)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD TOP BAR SECTION
|
||||
export const topBar = () => {
|
||||
return getAuxEnd(`/panel/account/bar`)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD RECENT ACTIONS SECTION
|
||||
export const recentActions = () => {
|
||||
return getAuxEnd(`/panel/account/actions`)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD PRODUCT DATA SECTION
|
||||
export const productData = () => {
|
||||
return getAuxEnd(`/panel/account/products`)
|
||||
}
|
||||
|
||||
// FUNCTION TO GET DASHBOARD PRODUCT URL DATA SECTION
|
||||
export const productsURL = () => {
|
||||
return getAuxEnd(`/panel/account/products/url`)
|
||||
}
|
||||
|
||||
export const MyProductData = (productID) => {
|
||||
const reqData = { product_id : productID}
|
||||
//console.log(reqData)
|
||||
return getAuxEnd(`/panel/myproduct/dash`,reqData)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
userDetails: {},
|
||||
};
|
||||
|
||||
export const userSlice = createSlice({
|
||||
name: "userDetails",
|
||||
initialState,
|
||||
reducers: {
|
||||
updateUserDetails: (state, action) => {
|
||||
state.userDetails = { ...action.payload };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { updateUserDetails } = userSlice.actions;
|
||||
|
||||
export default userSlice.reducer;
|
||||
@@ -0,0 +1,10 @@
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
|
||||
import userDetailReducer from "./UserDetails";
|
||||
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
userDetails: userDetailReducer,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
function debounceFunction(func, delay) {
|
||||
let timer;
|
||||
|
||||
return function(...args) {
|
||||
// Clear the previous timer if the function is called before the delay
|
||||
clearTimeout(timer);
|
||||
|
||||
// Set a new timer to execute the function after the specified delay
|
||||
timer = setTimeout(() => {
|
||||
func(...args);
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
|
||||
export default debounceFunction
|
||||
@@ -0,0 +1,9 @@
|
||||
let productPath = (product_uid) => {
|
||||
if (!product_uid) {
|
||||
return "/product/"; // require(`../assets/img/logo.png`);
|
||||
} else {
|
||||
return "/product/"+ product_uid; // require(`../assets/img/${location}`);
|
||||
}
|
||||
};
|
||||
|
||||
export default productPath
|
||||
@@ -0,0 +1,8 @@
|
||||
import React from 'react'
|
||||
import CSignup from '../component/auth/CSignup'
|
||||
|
||||
export default function CSignupPage() {
|
||||
return (
|
||||
<CSignup />
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
import ProductFactory from '../component/product/ProductFactory'
|
||||
export default function ProductPage() {
|
||||
return (
|
||||
<ProductFactory />
|
||||
)
|
||||
}
|
||||