Merge pull request 'main' (#1) from main into master
Reviewed-on: http://128.199.30.231/possibillion/atp-admin/pulls/1
This commit is contained in:
commit
236dea4729
4
.env
4
.env
@ -1,2 +1,2 @@
|
||||
PORT=3000
|
||||
CHOKIDAR_USEPOLLING=true
|
||||
PORT = 3000
|
||||
CHOKIDAR_USEPOLLING = true
|
BIN
.gitignore
vendored
BIN
.gitignore
vendored
Binary file not shown.
17
package.json
17
package.json
@ -30,13 +30,16 @@
|
||||
"coreui_library_short_version": "4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ckeditor/ckeditor5-build-classic": "^35.2.1",
|
||||
"@ckeditor/ckeditor5-react": "^5.0.2",
|
||||
"@coreui/chartjs": "^3.0.0",
|
||||
"@coreui/coreui": "^4.1.0",
|
||||
"@coreui/icons": "^2.1.0",
|
||||
"@coreui/icons-react": "^2.0.0",
|
||||
"@coreui/react": "^4.1.0",
|
||||
"@coreui/react": "^4.3.0",
|
||||
"@coreui/react-chartjs": "^2.0.0",
|
||||
"@coreui/utils": "^1.3.1",
|
||||
"@material-ui/core": "^4.12.4",
|
||||
"@reduxjs/toolkit": "^1.8.2",
|
||||
"@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
|
||||
"axios": "^0.25.0",
|
||||
@ -48,19 +51,23 @@
|
||||
"enzyme": "^3.11.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.2",
|
||||
"react": "18.2",
|
||||
"react-app-polyfill": "^2.0.0",
|
||||
"react-bootstrap": "^2.7.0",
|
||||
"react-date-picker": "^8.4.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-datepicker": "^4.8.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react-paginate": "^8.1.3",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-router-dom": "^6.7.0",
|
||||
"react-spinners": "^0.11.0",
|
||||
"react-time-picker": "^4.5.0",
|
||||
"redux": "4.1.2",
|
||||
"serve": "^13.0.2",
|
||||
"simplebar-react": "^2.3.6",
|
||||
"sweetalert": "^2.1.2",
|
||||
"sweetalert2": "^11.4.0",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack": "4.44.2",
|
||||
"xlsx": "^0.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -15,7 +15,7 @@
|
||||
<meta name="description" content="CoreUI for React - Open Source Bootstrap Admin Template">
|
||||
<meta name="author" content="Łukasz Holeczek">
|
||||
<meta name="keyword" content="Bootstrap,Admin,Template,Open,Source,CSS,SCSS,HTML,RWD,Dashboard,React">
|
||||
<title>CMP-Dashboard</title>
|
||||
<title>ATP-Dashboard</title>
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
@ -23,6 +23,8 @@
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
|
||||
<link rel="react" href="https://coreui.io/react/">
|
||||
|
||||
<!-- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> -->
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
|
@ -1,59 +0,0 @@
|
||||
import axios from "axios";
|
||||
|
||||
|
||||
|
||||
// };
|
||||
export const createCategory = (categoryData) => async (dispatch) => {
|
||||
try {
|
||||
dispatch({
|
||||
type: "NEW_CATEGORY_REQUEST",
|
||||
});
|
||||
|
||||
const { data } = await axios.post(
|
||||
`http://localhost:5000/api/category/create`,
|
||||
categoryData,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: "NEW_CATEGORY_SUCCESS",
|
||||
payload: data,
|
||||
});
|
||||
} catch (error) {
|
||||
dispatch({
|
||||
type: "NEW_CATEGORY_FAIL",
|
||||
payload: error.response.data.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
export const viewAllCategory = () => async (dispatch) => {
|
||||
try {
|
||||
dispatch({
|
||||
type: "ALL_CATEGORY_REQUEST",
|
||||
});
|
||||
|
||||
const { data } = await axios.post(
|
||||
`http://localhost:5000/api/directory/getAll`,
|
||||
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: "ALL_CATEGORY_SUCCESS",
|
||||
payload: data.data,
|
||||
});
|
||||
} catch (error) {
|
||||
dispatch({
|
||||
type: "ALL_CATEGORY_FAIL",
|
||||
payload: error.response.data.message,
|
||||
});
|
||||
}
|
||||
};
|
89
src/App.js
89
src/App.js
@ -1,11 +1,13 @@
|
||||
import React, { Component } from 'react'
|
||||
import React, { Component, Suspense } from 'react'
|
||||
import axios from 'axios';
|
||||
import { BrowserRouter, Route, Switch } from 'react-router-dom'
|
||||
import { Router, Route, Routes, HashRouter } from 'react-router-dom'
|
||||
import { useState, useEffect } from 'react';
|
||||
import './scss/style.scss'
|
||||
import ForgotPassword from './views/pages/register/ForgotPassword'
|
||||
import NewRegister from './views/pages/register/NewRegister'
|
||||
import ProtectedRoute from './components/ProtectedRoute';
|
||||
import { isAutheticated } from './auth';
|
||||
|
||||
|
||||
const loading = (
|
||||
<div className="pt-3 text-center">
|
||||
@ -19,36 +21,69 @@ const DefaultLayout = React.lazy(() => import('./layout/DefaultLayout'))
|
||||
// Pages
|
||||
const Login = React.lazy(() => import('./views/pages/login/Login'))
|
||||
const Register = React.lazy(() => import('./views/pages/register/Change_password'))
|
||||
const Page404 = React.lazy(() => import('./views/pages/page404/Page404'))
|
||||
const Page404 = React.lazy(() => import('./views/pages/register/page404/Page404'))
|
||||
const Page500 = React.lazy(() => import('./views/pages/page500/Page500'))
|
||||
|
||||
class App extends Component {
|
||||
render() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<React.Suspense fallback={loading}>
|
||||
<Switch>
|
||||
< Route exact path="/" name="Login Page" render={(props) => <Login {...props} />} />
|
||||
const App = () => {
|
||||
|
||||
<Route exact path="/forgot" name="Forgot Page" render={(props) => <ForgotPassword {...props} />} />
|
||||
<Route exact path="/newRegister" name="Register Page" render={(props) => <NewRegister {...props} />} />
|
||||
const [userdata, setUserData] = useState(null)
|
||||
const token = isAutheticated();
|
||||
|
||||
<Route exact path="/404" name="Page 404" render={(props) => <Page404 {...props} />} />
|
||||
<Route exact path="/500" name="Page 500" render={(props) => <Page500 {...props} />} />
|
||||
useEffect(() => {
|
||||
const getUser = async () => {
|
||||
let existanceData = localStorage.getItem("authToken");
|
||||
if (!existanceData) {
|
||||
// console.log(existanceData.userData)
|
||||
setUserData(false)
|
||||
} else {
|
||||
try {
|
||||
// console.log('requesting user data from server')
|
||||
let response = await axios.get(`/api/v1/user/details`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
// console.log(response.data)
|
||||
const data = response.data
|
||||
if (data.success && data.user.role === 'admin') {
|
||||
|
||||
|
||||
{/* localStorage.getItem('authToken') ? */}
|
||||
<Route path="/" name="Home" render={(props) => <DefaultLayout {...props} />} />
|
||||
{/* < ProtectedRoute path="/" name="Home" render={(props) => <DefaultLayout {...props} />} /> */}
|
||||
|
||||
|
||||
|
||||
|
||||
</Switch>
|
||||
</React.Suspense>
|
||||
</BrowserRouter>
|
||||
)
|
||||
setUserData(data.user);
|
||||
} else {
|
||||
setUserData(false)
|
||||
}
|
||||
|
||||
}
|
||||
catch (err) {
|
||||
setUserData(false)
|
||||
console.log(err);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
getUser()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
|
||||
<HashRouter>
|
||||
<Suspense fallback={loading}>
|
||||
<Routes>
|
||||
<Route exact path="/" name="Login Page" element={<Login />} />
|
||||
<Route exact path="/register" name="Register Page" element={<NewRegister />} />
|
||||
<Route exact path="/password/forgot" name="Forgot Page" element={<ForgotPassword />} />
|
||||
<Route exact path="/404" name="Page 404" element={<Page404 />} />
|
||||
<Route exact path="/500" name="Page 500" element={<Page500 />} />
|
||||
|
||||
<Route path="/" name="Home" element={userdata?.role === "admin" ? <DefaultLayout />
|
||||
:
|
||||
userdata === false ? <Login /> : <div></div>} />
|
||||
|
||||
|
||||
<Route path="*" name="Home" element={<DefaultLayout />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</HashRouter>
|
||||
|
||||
)
|
||||
}
|
||||
//@coreui/coreui-free-react-admin-template@4.1.1
|
||||
export default App
|
||||
|
106
src/_nav.js
106
src/_nav.js
@ -1,19 +1,32 @@
|
||||
import React from 'react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import {
|
||||
cilAddressBook,
|
||||
cilAppsSettings,
|
||||
cilBell,
|
||||
cilCalculator,
|
||||
cilChartPie,
|
||||
cilClipboard,
|
||||
cilCommand,
|
||||
cilCursor,
|
||||
cilDrop,
|
||||
cilFace,
|
||||
cilFilterSquare,
|
||||
cilMedicalCross,
|
||||
cilMoney,
|
||||
cilMugTea,
|
||||
cilNewspaper,
|
||||
cilNotes,
|
||||
cilPencil,
|
||||
cilPuzzle,
|
||||
cilSitemap,
|
||||
cilSpeedometer,
|
||||
cilStar,
|
||||
cilTablet,
|
||||
cilTennisBall,
|
||||
cilUser,
|
||||
|
||||
|
||||
} from '@coreui/icons'
|
||||
import { CNavGroup, CNavItem, CNavTitle } from '@coreui/react'
|
||||
|
||||
@ -28,22 +41,97 @@ const _nav = [
|
||||
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Category',
|
||||
icon: <CIcon icon={cilPencil} customClassName="nav-icon" />,
|
||||
to: '/category',
|
||||
name: 'Products',
|
||||
icon: <CIcon icon={cilClipboard} customClassName="nav-icon" />,
|
||||
to: '/products',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Directory',
|
||||
icon: <CIcon icon={cilDrop} customClassName="nav-icon" />,
|
||||
to: '/bisuness',
|
||||
name: 'Temples',
|
||||
icon: <CIcon icon={cilTennisBall} customClassName="nav-icon" />,
|
||||
to: '/temples',
|
||||
},
|
||||
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Users',
|
||||
icon: <CIcon icon={cilUser} customClassName="nav-icon" />,
|
||||
to: '/users',
|
||||
},
|
||||
{
|
||||
component: CNavGroup,
|
||||
name: 'Configuration',
|
||||
icon: <CIcon icon={cilAppsSettings} customClassName="nav-icon" />,
|
||||
items: [
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Cities',
|
||||
icon: <CIcon icon={cilNotes} customClassName="nav-icon" />,
|
||||
to: '/cities',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'News',
|
||||
icon: <CIcon icon={cilNewspaper} customClassName="nav-icon" />,
|
||||
to: '/news',
|
||||
name: 'States',
|
||||
icon: <CIcon icon={cilNotes} customClassName="nav-icon" />,
|
||||
to: '/states',
|
||||
},
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Standard Shipping',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/shipping',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Custom Shipping',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/custom-shipping',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Pincode',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/pincode',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Tax Rates',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/tax',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Pages',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/page',
|
||||
// },
|
||||
// {
|
||||
// component: CNavItem,
|
||||
// name: 'Terms of Use',
|
||||
// icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
// to: '/terms_of_use',
|
||||
// },
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Social Media',
|
||||
icon: <CIcon icon={cilMedicalCross} customClassName="nav-icon" />,
|
||||
to: '/socialmedia',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Address',
|
||||
icon: <CIcon icon={cilAddressBook} customClassName="nav-icon" />,
|
||||
to: '/address',
|
||||
},
|
||||
{
|
||||
component: CNavItem,
|
||||
name: 'Logos',
|
||||
icon: <CIcon icon={cilCommand} customClassName="nav-icon" />,
|
||||
to: '/logo',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { Suspense } from 'react'
|
||||
import { Redirect, Route, Switch } from 'react-router-dom'
|
||||
import { Navigate, Route, Routes } from 'react-router-dom'
|
||||
import { CContainer, CSpinner } from '@coreui/react'
|
||||
|
||||
// routes config
|
||||
@ -9,26 +9,22 @@ const AppContent = () => {
|
||||
return (
|
||||
<CContainer lg>
|
||||
<Suspense fallback={<CSpinner color="primary" />}>
|
||||
<Switch>
|
||||
<Routes>
|
||||
{routes.map((route, idx) => {
|
||||
return (
|
||||
route.component && (
|
||||
route.element && (
|
||||
<Route
|
||||
key={idx}
|
||||
path={route.path}
|
||||
exact={route.exact}
|
||||
name={route.name}
|
||||
render={(props) => (
|
||||
<>
|
||||
<route.component {...props} />
|
||||
</>
|
||||
)}
|
||||
element={<route.element />}
|
||||
/>
|
||||
)
|
||||
)
|
||||
})}
|
||||
<Redirect from="/" to="/dashboard" />
|
||||
</Switch>
|
||||
<Route path="/" element={<Navigate to="dashboard" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</CContainer>
|
||||
)
|
||||
|
@ -6,9 +6,9 @@ const AppFooter = () => {
|
||||
<CFooter>
|
||||
<div>
|
||||
|
||||
<span className="ms-1">{new Date().getFullYear()} © CMP.</span>
|
||||
<span className="ms-1">{new Date().getFullYear()} © Any Time Prasad ( ATP ) .</span>
|
||||
</div>
|
||||
\
|
||||
|
||||
</CFooter>
|
||||
)
|
||||
}
|
||||
|
@ -32,12 +32,12 @@ const AppHeader = () => {
|
||||
<CIcon icon={cilMenu} size="lg" />
|
||||
</CHeaderToggler>
|
||||
<CHeaderBrand className="mx-auto d-md-none" to="/">
|
||||
<h1>Courier</h1>
|
||||
<h3>Any Time Prasad</h3>
|
||||
</CHeaderBrand>
|
||||
<CHeaderNav className="d-none d-md-flex me-auto">
|
||||
<CNavItem>
|
||||
<CNavLink to="/dashboard" component={NavLink} activeClassName="active">
|
||||
Dashboard
|
||||
ATP Dashboard
|
||||
</CNavLink>
|
||||
</CNavItem>
|
||||
{/* <CNavItem>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
|
||||
import { CSidebar, CSidebarBrand, CSidebarNav, CSidebarToggler } from '@coreui/react'
|
||||
@ -14,12 +14,45 @@ import 'simplebar/dist/simplebar.min.css'
|
||||
|
||||
// sidebar nav config
|
||||
import navigation from '../_nav'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
import axios from 'axios'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
const AppSidebar = () => {
|
||||
const dispatch = useDispatch()
|
||||
const unfoldable = useSelector((state) => state.sidebarUnfoldable)
|
||||
const sidebarShow = useSelector((state) => state.sidebarShow)
|
||||
|
||||
///----------------------//
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const token = isAutheticated()
|
||||
|
||||
// urlcreated images
|
||||
|
||||
const [HeaderlogoUrl, setHeaderlogoUrl] = useState('')
|
||||
const [FooterlogoUrl, setFooterlogoUrl] = useState('')
|
||||
const [AdminlogoUrl, setAdminlogoUrl] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
async function getConfiguration() {
|
||||
const configDetails = await axios.get(`/api/config`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
console.log(configDetails.data.result)
|
||||
configDetails.data.result.map((item) => {
|
||||
setHeaderlogoUrl(item?.logo[0]?.Headerlogo)
|
||||
setFooterlogoUrl(item?.logo[0]?.Footerlogo)
|
||||
setAdminlogoUrl(item?.logo[0]?.Adminlogo)
|
||||
})
|
||||
}
|
||||
getConfiguration()
|
||||
}, [])
|
||||
|
||||
console.log(HeaderlogoUrl)
|
||||
//---------------------------//
|
||||
return (
|
||||
<CSidebar
|
||||
position="fixed"
|
||||
@ -29,9 +62,10 @@ const AppSidebar = () => {
|
||||
dispatch({ type: 'set', sidebarShow: visible })
|
||||
}}
|
||||
>
|
||||
<CSidebarBrand className="d-none bg-info d-md-flex" to="/">
|
||||
<CSidebarBrand className="d-none d-md-flex" style={{ background: 'rgb(140, 213, 213)' }} to="/">
|
||||
{/* <CIcon className="sidebar-brand-full" icon={logoNegative} height={35} /> */}
|
||||
<h1>CMP</h1>
|
||||
|
||||
{HeaderlogoUrl ? <Link to='/dashboard'><img src={HeaderlogoUrl} alt={`${<h1>ATP Dashboard</h1>}`} /></Link> : <h1>ATP Dashboard</h1>}
|
||||
{/* <CIcon className="sidebar-brand-narrow" height={35} /> */}
|
||||
<CIcon className="sidebar-brand-narrow" icon={sygnet} height={35} />
|
||||
</CSidebarBrand>
|
||||
|
@ -53,6 +53,7 @@ export const AppSidebarNav = ({ items }) => {
|
||||
{...rest}
|
||||
>
|
||||
{item.items?.map((item, index) =>
|
||||
|
||||
item.items ? navGroup(item, index) : navItem(item, index),
|
||||
)}
|
||||
</Component>
|
||||
@ -62,7 +63,8 @@ export const AppSidebarNav = ({ items }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{items &&
|
||||
items.map((item, index) => (item.items ? navGroup(item, index) : navItem(item, index)))}
|
||||
items.map((item, index) =>
|
||||
(item.items ? navGroup(item, index) : navItem(item, index)))}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState, } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
const ProtectedRoute = (props) => {
|
||||
let Cmp = props;
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
useEffect(() => {
|
||||
if (!localStorage.getItem('authToken'))
|
||||
history.push('/')
|
||||
history('/')
|
||||
}, [])
|
||||
return (
|
||||
<>
|
||||
|
@ -24,26 +24,56 @@ import {
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import swal from 'sweetalert';
|
||||
|
||||
import avatar8 from './../../assets/images/avatars/8.jpg'
|
||||
import userImage from './../../assets/images/avatars/1.jpg'
|
||||
import { Link } from 'react-router-dom'
|
||||
// import { signout } from 'src/auth'
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import { useState } from 'react';
|
||||
|
||||
|
||||
const AppHeaderDropdown = () => {
|
||||
let history = useHistory();
|
||||
const [userData, setUserData] = useState()
|
||||
let history = useNavigate();
|
||||
const signout = async () => {
|
||||
localStorage.removeItem('authToken')
|
||||
// let res = await axios.get(
|
||||
// `http://localhost:5000/api/user/logOut`
|
||||
// );
|
||||
// if (res.success == true) {
|
||||
swal("success!", "Logged Out", "success");
|
||||
history.push("/");
|
||||
// }
|
||||
history("/");
|
||||
}
|
||||
|
||||
//for user image
|
||||
|
||||
const getUser = async () => {
|
||||
let token = localStorage.getItem("authToken");
|
||||
try {
|
||||
let response = await axios.get(`/api/v1/user/details`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (response.data.success === true) {
|
||||
setUserData(response.data.user)
|
||||
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
|
||||
console.log(err);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getUser()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<CDropdown variant="nav-item">
|
||||
<CDropdownToggle placement="bottom-end" className="py-0" caret={false}>
|
||||
<CAvatar src={avatar8} size="md" />
|
||||
{/* {userData && userData ? <CAvatar src={userData.avatar.url} size="md" /> : */}
|
||||
<CAvatar src={userImage} size="md" />
|
||||
</CDropdownToggle>
|
||||
<CDropdownMenu className="pt-0" placement="bottom-end">
|
||||
<CDropdownHeader className="bg-light fw-semibold py-2">Account</CDropdownHeader>
|
||||
@ -99,6 +129,12 @@ const AppHeaderDropdown = () => {
|
||||
</CBadge> */}
|
||||
</CDropdownItem>
|
||||
{/* <CDropdownDivider /> */}
|
||||
<Link to='/profile/edit'>
|
||||
<CDropdownItem>
|
||||
<CIcon icon={cilUser} className="me-2" />
|
||||
Edit Profile
|
||||
</CDropdownItem>
|
||||
</Link>
|
||||
<Link to='/change_password'>
|
||||
<CDropdownItem>
|
||||
<CIcon icon={cilPencil} className="me-2" />
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
import '@coreui/coreui/dist/css/coreui.min.css';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import 'react-app-polyfill/stable'
|
||||
import 'core-js'
|
||||
import React from 'react'
|
||||
@ -10,7 +11,7 @@ import store from './store'
|
||||
import axios from 'axios'
|
||||
|
||||
const setupAxios = () => {
|
||||
axios.defaults.baseURL = 'https://cms-api-dashboard.herokuapp.com/';
|
||||
axios.defaults.baseURL = 'https://atpapi.checkapp.one'
|
||||
//axios.defaults.baseURL = 'http://localhost:5000'
|
||||
axios.defaults.headers = {
|
||||
'Cache-Control': 'no-cache,no-store',
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { createReducer } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
loading: true,
|
||||
};
|
||||
|
||||
export const newCategoryReducer = createReducer(
|
||||
{},
|
||||
{
|
||||
NEW_CATEGORY_REQUEST: (state) => {
|
||||
state.loading = true;
|
||||
},
|
||||
NEW_CATEGORY_SUCCESS: (state, action) => {
|
||||
state.loading = false;
|
||||
state.message = action.payload;
|
||||
},
|
||||
NEW_CATEGORY_FAIL: (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = action.payload;
|
||||
},
|
||||
CLEAR_ERRORS: (state) => {
|
||||
state.error = null;
|
||||
},
|
||||
CLEAR_MESSAGE: (state) => {
|
||||
state.message = null;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
///
|
||||
export const AllcategoryReducer = createReducer(initialState, {
|
||||
ALL_CATEGORY_REQUEST: (state) => {
|
||||
state.loading = true;
|
||||
},
|
||||
ALL_CATEGORY_SUCCESS: (state, action) => {
|
||||
state.loading = false;
|
||||
state.category = action.payload;
|
||||
},
|
||||
ALL_CATEGORY_FAIL: (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = action.payload;
|
||||
},
|
||||
CLEAR_ERRORS: (state) => {
|
||||
state.error = null;
|
||||
},
|
||||
});
|
@ -1,61 +0,0 @@
|
||||
import { createReducer } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
loading: true,
|
||||
};
|
||||
export const loginReducer = createReducer(
|
||||
{},
|
||||
{
|
||||
LOGIN_REQUEST: (state) => {
|
||||
state.loading = true;
|
||||
state.isAuthenticated = false;
|
||||
},
|
||||
LOGIN_SUCCESS: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = true;
|
||||
state.message = action.payload;
|
||||
},
|
||||
LOGIN_FAILURE: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = false;
|
||||
state.error = action.payload;
|
||||
},
|
||||
|
||||
LOAD_USER_REQUEST: (state) => {
|
||||
state.loading = true;
|
||||
state.isAuthenticated = false;
|
||||
},
|
||||
LOAD_USER_SUCCESS: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = true;
|
||||
state.user = action.payload;
|
||||
},
|
||||
LOAD_USER_FAILURE: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = false;
|
||||
state.error = action.payload;
|
||||
},
|
||||
|
||||
LOGOUT_REQUEST: (state) => {
|
||||
state.loading = true;
|
||||
},
|
||||
LOGOUT_SUCCESS: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = false;
|
||||
state.user = null;
|
||||
state.message = action.payload;
|
||||
},
|
||||
LOGOUT_FAILURE: (state, action) => {
|
||||
state.loading = false;
|
||||
state.isAuthenticated = true;
|
||||
state.error = action.payload;
|
||||
},
|
||||
|
||||
CLEAR_ERRORS: (state) => {
|
||||
state.error = null;
|
||||
},
|
||||
CLEAR_MESSAGE: (state) => {
|
||||
state.message = null;
|
||||
},
|
||||
}
|
||||
);
|
101
src/routes.js
101
src/routes.js
@ -1,50 +1,83 @@
|
||||
import React from 'react'
|
||||
//Category
|
||||
import Category from './views/Category/Category'
|
||||
import EditCategory from './views/Category/EditCategory'
|
||||
import AddCategeory from './views/Category/AddCategory'
|
||||
//Bisuness
|
||||
import Bisuness from './views/Directory/Bisuness'
|
||||
import EditBisuness from "./views/Directory/EditBisuness"
|
||||
import Add_Business from './views/Directory/Add_Business'
|
||||
import View_Business from './views/Directory/View_Bisuness'
|
||||
//news
|
||||
import AddNews from "./views/News/AddNews"
|
||||
import EditNews from "./views/News/EditNews"
|
||||
import News from "./views/News/News"
|
||||
import ViewNews from "./views/News/ViewNews"
|
||||
|
||||
|
||||
// DashBoard
|
||||
const Change_Password = React.lazy(() => import('./views/pages/register/Change_password'))
|
||||
const EditProfile = React.lazy(() => import('./views/Profile/EditProfile'))
|
||||
const Dashboard = React.lazy(() => import('./views/dashboard/Dashboard'))
|
||||
|
||||
|
||||
import Profile from './views/Profile/Profile'
|
||||
import EditProfile from './views/Profile/EditProfile'
|
||||
const Dashboard = React.lazy(() => import('./views/dashboard/Dashboard'))
|
||||
///
|
||||
//Cities
|
||||
import Cities from './views/configuration/cities/Cities.js'
|
||||
import AddCity from './views/configuration/cities/AddCity.js'
|
||||
import EditCity from './views/configuration/cities/EditCity.js'
|
||||
//states
|
||||
import EditState from './views/configuration/states/EditStates.js'
|
||||
import AddState from './views/configuration/states/AddState.js'
|
||||
import States from './views/configuration/states/States.js'
|
||||
//social media,address,logo
|
||||
import Socialmedia from './views/configuration/Socialmedia.js'
|
||||
import Address from './views/configuration/Address.js'
|
||||
import Logo from './views/configuration/Logo.js'
|
||||
import Login from './views/pages/login/Login'
|
||||
//temple
|
||||
import Temples from './views/Temples/Temples'
|
||||
import AddTemple from './views/Temples/AddTemple'
|
||||
import EditTemple from './views/Temples/EditTemple'
|
||||
import Products from './views/Products/Products'
|
||||
//product
|
||||
import AddProduct from './views/Products/AddProduct'
|
||||
import EditProduct from './views/Products/EditProduct'
|
||||
import ViewProduct from './views/Products/ViewProduct'
|
||||
|
||||
const routes = [
|
||||
|
||||
{ path: '/', exact: true, name: 'Home' },
|
||||
{ path: '/change_password', name: 'Change Password', component: Change_Password },
|
||||
{ path: '/edit', name: 'Change Password', component: EditProfile },
|
||||
// { path: '/profile', name: 'Change Password', component: Profile },
|
||||
{ path: '/change_password', name: 'Change Password', element: Change_Password },
|
||||
{ path: '/profile/edit', name: 'Edit Profile', element: EditProfile },
|
||||
// { path: '/profile', name: 'Profile', element: Profile },
|
||||
|
||||
//Category route
|
||||
{ path: '/addCategory', name: 'AddCategeory', component: AddCategeory },
|
||||
{ path: '/category/edit/:id', name: 'EditCategory', component: EditCategory },
|
||||
{ path: '/category', name: 'Category', component: Category },
|
||||
|
||||
//Directory-Bisuness route
|
||||
{ path: '/view_bisuness/:id', name: 'view_bisuness_directory', component: View_Business },
|
||||
{ path: '/add_bisuness', name: 'Add_bisuness_directory', component: Add_Business },
|
||||
{ path: '/bisuness/edit/:id', name: 'EditBisuness', component: EditBisuness },
|
||||
{ path: '/bisuness', name: 'bisuness', component: Bisuness },
|
||||
//News route
|
||||
{ path: '/news/view/:id', name: 'ViewNews', component: ViewNews },
|
||||
{ path: '/addNews', name: 'addNews', component: AddNews },
|
||||
{ path: '/news/edit/:id', name: 'EditNews', component: EditNews },
|
||||
{ path: '/news', name: 'news', component: News },
|
||||
//Product
|
||||
{ path: '/products', name: 'products', element: Products },
|
||||
{ path: '/product/add', name: 'Add products', element: AddProduct },
|
||||
{ path: '/product/edit/:id', name: 'Edit products', element: EditProduct },
|
||||
{ path: '/product/view/:id', name: 'view products', element: ViewProduct },
|
||||
|
||||
|
||||
|
||||
//Temple
|
||||
{ path: '/temples', name: 'Temples', element: Temples },
|
||||
{ path: '/temple/add', name: 'Add Temple', element: AddTemple },
|
||||
{ path: '/temple/edit/:id', name: 'Edit Temples', element: EditTemple },
|
||||
|
||||
//dashboard
|
||||
{ path: '/dashboard', name: 'Dashboard', component: Dashboard },
|
||||
|
||||
{ path: '/dashboard', name: 'Dashboard', element: Dashboard },
|
||||
|
||||
//------------settings------------------------//
|
||||
//cities
|
||||
{ path: '/cities', name: 'Cities', element: Cities },
|
||||
{ path: '/cities/add', name: 'Add City', element: AddCity },
|
||||
{ path: '/cities/edit/:id', name: 'Edit City', element: EditCity },
|
||||
//states
|
||||
{ path: '/states', name: 'States', element: States },
|
||||
{ path: '/states/add', name: 'Add State', element: AddState },
|
||||
{ path: '/states/edit/:id', name: 'Edit State', element: EditState },
|
||||
|
||||
//
|
||||
|
||||
{ path: '/socialmedia', name: 'Social Media', element: Socialmedia },
|
||||
{ path: '/address', name: 'Address', element: Address },
|
||||
{ path: '/logo', name: 'Logo', element: Logo },
|
||||
// -------------------------------------------//
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
]
|
||||
|
||||
export default routes
|
||||
|
@ -1,14 +1,14 @@
|
||||
// If you want to override variables do it here
|
||||
@import "variables";
|
||||
|
||||
$enable-ltr: true;
|
||||
$enable-rtl: true;
|
||||
|
||||
// Import CoreUI for React components library
|
||||
@import "@coreui/coreui/scss/coreui";
|
||||
|
||||
// Import CoreUI for React components library
|
||||
//@import "@coreui/coreui/scss/coreui";
|
||||
// Import Chart.js custom tooltips styles
|
||||
@import "@coreui/chartjs/scss/coreui-chartjs";
|
||||
//@import "@coreui/chartjs";
|
||||
|
||||
@import "layout";
|
||||
@import "example";
|
||||
|
48
src/store.js
48
src/store.js
@ -1,31 +1,31 @@
|
||||
// import { createStore } from 'redux'
|
||||
import { createStore } from 'redux'
|
||||
|
||||
// const initialState = {
|
||||
// sidebarShow: true,
|
||||
// }
|
||||
const initialState = {
|
||||
sidebarShow: true,
|
||||
}
|
||||
|
||||
// const changeState = (state = initialState, { type, ...rest }) => {
|
||||
// switch (type) {
|
||||
// case 'set':
|
||||
// return { ...state, ...rest }
|
||||
// default:
|
||||
// return state
|
||||
// }
|
||||
// }
|
||||
const changeState = (state = initialState, { type, ...rest }) => {
|
||||
switch (type) {
|
||||
case 'set':
|
||||
return { ...state, ...rest }
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
// const store = createStore(changeState)
|
||||
// export default store
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import { newCategoryReducer, AllcategoryReducer } from "./reducers/categoryReducer.js";
|
||||
import { loginReducer } from "./reducers/directoryReducer.js";
|
||||
const store = createStore(changeState)
|
||||
export default store
|
||||
// import { configureStore } from "@reduxjs/toolkit";
|
||||
// import { newCategoryReducer, AllcategoryReducer } from "./reducers/categoryReducer.js";
|
||||
// import { loginReducer } from "./reducers/directoryReducer.js";
|
||||
|
||||
const store = configureStore({
|
||||
reducer: {
|
||||
// const store = configureStore({
|
||||
// reducer: {
|
||||
|
||||
newCategory: newCategoryReducer,
|
||||
AllCategory: AllcategoryReducer,
|
||||
// newCategory: newCategoryReducer,
|
||||
// AllCategory: AllcategoryReducer,
|
||||
|
||||
},
|
||||
});
|
||||
// },
|
||||
// });
|
||||
|
||||
export default store;
|
||||
// export default store;
|
@ -1,141 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
//import Footer from "../../Footer";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
CCol,
|
||||
CContainer,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CInputGroup,
|
||||
CInputGroupText,
|
||||
CRow,
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilLockLocked, cilUser } from '@coreui/icons'
|
||||
const AddProduct = () => {
|
||||
// const { token } = isAutheticated();
|
||||
let history = useHistory();
|
||||
const [image, setImage] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const myForm = new FormData();
|
||||
|
||||
myForm.set("name", name);
|
||||
|
||||
|
||||
myForm.set("image", image);
|
||||
setLoading({ loading: true });
|
||||
// console.log(image)
|
||||
let res = await axios.post(
|
||||
`/api/category/create`, myForm,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": 'multipart/form-data',
|
||||
// Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
//console.log(res.data.data.name)
|
||||
if (res.data) {
|
||||
swal("success!", "Category Added Successfully!", "success");
|
||||
history.goBack();
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleImage = (e) => {
|
||||
const files = e.target.files[0];
|
||||
// console.log(files)
|
||||
setImage(files);
|
||||
|
||||
};
|
||||
//
|
||||
const onCancel = () => {
|
||||
// window.location = "/comproducts";
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-light min-vh-70 d-flex flex-row ">
|
||||
<CContainer>
|
||||
<CRow className="align-left w-140">
|
||||
<CCol md={19} lg={27} xl={16}>
|
||||
<CCard className="mx-4">
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h3 className="mb-4 justify-content-center">Add Category</h3>
|
||||
<div>
|
||||
<div>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
value={name}
|
||||
placeholder="Name" />
|
||||
</CInputGroup>
|
||||
|
||||
<CInputGroup className="mb-3">
|
||||
|
||||
{/* <CIcon icon={cilLockLocked} /> */}
|
||||
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
</CInputGroup>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success btn-login waves-effect waves-light"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" ml-2 btn btn-warning btn-cancel waves-effect waves-light"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CContainer>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddProduct
|
@ -1,178 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
|
||||
function Products() {
|
||||
const [category, setCategory] = useState([])
|
||||
const [state, setState] = useState({
|
||||
products: [],
|
||||
page: 1,
|
||||
limit: 10,
|
||||
totalProducts: 0,
|
||||
pages: 1,
|
||||
});
|
||||
|
||||
window.scrollTo({ behavior: "smooth", top: "0px" });
|
||||
|
||||
const { products, page, limit, totalProducts, pages } = state;
|
||||
|
||||
const changeState = (newState) =>
|
||||
setState((prevState) => ({ ...prevState, ...newState }));
|
||||
|
||||
const { token } = isAutheticated();
|
||||
|
||||
const getProducts = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/category/getAll`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
// console.log(res.data.category[0].image.url)
|
||||
setCategory(res.data.category)
|
||||
// console.log(category[0].addedOn)
|
||||
changeState({
|
||||
...res.data,
|
||||
pages: Math.ceil(res.data.totalProducts / limit),
|
||||
});
|
||||
}, [limit, page, token]);
|
||||
|
||||
useEffect(() => {
|
||||
getProducts();
|
||||
}, [getProducts]);
|
||||
|
||||
// const getTotalPages = useMemo(() => {
|
||||
// const length = pages > 1 ? pages : totalProducts ? 1 : 0;
|
||||
// return Array.from({ length }, (_, i) => i + 1);
|
||||
// }, [pages, totalProducts]);
|
||||
|
||||
// console.log(getTotalPages);
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
let status = window.confirm("Do you want to delete");
|
||||
if (!status) return;
|
||||
|
||||
let res = await axios.delete(`/api/category/delete/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
console.log(res)
|
||||
if (res.data.success == true) {
|
||||
swal("success!", "Category Deleted Successfully!", "success");
|
||||
window.location.reload();
|
||||
// if (res.status === 200) window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//change time formate
|
||||
function formatAMPM(date) {
|
||||
var hours = new Date(date).getHours();
|
||||
var minutes = new Date(date).getMinutes();
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">CMP-Category</h4>
|
||||
<Link to="/addCategory"><button type="button" className="btn btn-info float-end mb-3 ml-4"> + Add Category</button></Link>
|
||||
{/* <div className="page-title-right">
|
||||
<ol className="breadcrumb m-0">
|
||||
<li className="breadcrumb-item">
|
||||
<Link to="/dashboard">CMD-App</Link>
|
||||
</li>
|
||||
<li className="breadcrumb-item">CMD-Category</li>
|
||||
</ol>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Image</th>
|
||||
<th>Added On</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{category && category.map((item, index) =>
|
||||
<tr>
|
||||
<td>{item?.name}</td>
|
||||
<td>
|
||||
<img src={`${item?.image.url}`} width="50" alt="" /></td>
|
||||
<td>
|
||||
{/* {item?.addedOn} */}
|
||||
{new Date(`${item?.addedOn}`).toDateString()}<span> , {`${formatAMPM(item?.addedOn)}`}</span>
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<Link to={`/category/edit/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" mx-2 btn btn-primary btn-sm waves-effect waves-light btn-table ml-2"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDelete(`${item._id}`)}
|
||||
className=" btn btn-danger btn-sm waves-effect waves-light btn-table ml-2"
|
||||
id="sa-params"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Products;
|
@ -1,152 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
//import Footer from "../../Footer";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
CCol,
|
||||
CContainer,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CInputGroup,
|
||||
CInputGroupText,
|
||||
CRow,
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilLockLocked, cilUser } from '@coreui/icons'
|
||||
const AddProduct = () => {
|
||||
// const { token } = isAutheticated();
|
||||
let history = useHistory();
|
||||
const { id } = useParams();
|
||||
// console.log(id)
|
||||
const [image, setImage] = useState("");
|
||||
const [name, setName] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
useEffect(async () => {
|
||||
const res = await axios.get(`/api/category/getOne/${id}`, {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
});
|
||||
|
||||
|
||||
setName(res.data.category.name)
|
||||
}, [id]);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const myForm = new FormData();
|
||||
|
||||
myForm.set("name", name);
|
||||
|
||||
|
||||
myForm.set("image", image);
|
||||
setLoading({ loading: true });
|
||||
// console.log(image)
|
||||
let res = await axios.put(
|
||||
`/api/category/update/${id}`, myForm,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": 'multipart/form-data',
|
||||
// Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
//console.log(res.data.data.name)
|
||||
if (res.data) {
|
||||
swal("success!", "Category Edited Successfully!", "success");
|
||||
history.goBack();
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleImage = (e) => {
|
||||
const files = e.target.files[0];
|
||||
// console.log(files)
|
||||
setImage(files);
|
||||
|
||||
};
|
||||
//
|
||||
const onCancel = () => {
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-light w-100 min-vh-70 d-flex flex-row ">
|
||||
<CContainer className="w-100 ">
|
||||
<CRow className="align-left w-140">
|
||||
<CCol md={19} lg={27} xl={16}>
|
||||
<CCard className="mr-4 mx-4">
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h3 className="mb-4 justify-content-center">Edit {name} Category</h3>
|
||||
<div>
|
||||
<div>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
value={name}
|
||||
placeholder="Name" />
|
||||
</CInputGroup>
|
||||
|
||||
<CInputGroup className="mb-3">
|
||||
|
||||
{/* <CIcon icon={cilLockLocked} /> */}
|
||||
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
</CInputGroup>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success btn-login waves-effect waves-light"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" ml-2 btn btn-warning btn-cancel waves-effect waves-light"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CContainer>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddProduct
|
@ -1,464 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import { Country, State, City } from "country-state-city";
|
||||
import swal from 'sweetalert';
|
||||
|
||||
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
const Add_Business = () => {
|
||||
const [categoryName, setCategoryName] = useState([]);
|
||||
|
||||
const { token } = isAutheticated();
|
||||
|
||||
let history = useHistory();
|
||||
const [state, setState] = useState({
|
||||
name: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
Bname: "",
|
||||
Sname: "",
|
||||
country: "",
|
||||
city: "",
|
||||
loading: false,
|
||||
description: "",
|
||||
category: "",
|
||||
status: "",
|
||||
Glocation: "",
|
||||
LinkedinUrl: "",
|
||||
FacebookUrl: "",
|
||||
InstagramUrl: ""
|
||||
});
|
||||
|
||||
|
||||
const { description, loading } = state;
|
||||
const changeState = (newState) =>
|
||||
setState((prevState) => ({ ...prevState, ...newState }));
|
||||
|
||||
|
||||
const handleChange = (e) => {
|
||||
changeState({ ...state, [e.target.name]: e.target.value })
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
const fetchCategory = useCallback(async () => {
|
||||
const res = await axios.get(`/api/category/getAll`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(res.data.category);
|
||||
setCategoryName(res.data.category)
|
||||
if (res.status === 200) changeState({ ...res.data });
|
||||
}, [token]);
|
||||
|
||||
useEffect(async () => {
|
||||
|
||||
|
||||
|
||||
|
||||
fetchCategory();
|
||||
|
||||
}, [fetchCategory]);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!(name || description || phone || email || Bname || Sname || city)) {
|
||||
alert("Please fill required field ");
|
||||
return;
|
||||
}
|
||||
changeState({ loading: true });
|
||||
|
||||
let res = await axios.post(
|
||||
`/api/directory/create/`,
|
||||
{
|
||||
...state,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
//if (res.status === 200) window.location.reload();
|
||||
console.log(res.status == 201)
|
||||
if (res.status == 201) {
|
||||
changeState({ loading: false });
|
||||
swal("Add Business successfully!");
|
||||
history.goBack()
|
||||
}
|
||||
};
|
||||
const onCancel = () => {
|
||||
// window.location = "/comproducts";
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// console.log(state)
|
||||
return (
|
||||
<>
|
||||
<div className=" main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="form-group text-right">
|
||||
<span className=" fs-2 text-xl-start font-weight-bold float-start">Add Bisuness</span>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success mt-1 mb-0 my-1 btn btn-success btn-login waves-effect waves-light mr-1"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" mt-1 ml-2 btn btn-warning btn-cancel waves-effect waves-light mr-3"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- Save options Ends--> */}
|
||||
|
||||
{/* <!-- Row 1 Begins --> */}
|
||||
<div className="row">
|
||||
{/* <!--Left Column Begins--> */}
|
||||
<div className="col-lg-8">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={state.name}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
phone*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
name="phone"
|
||||
value={state.phone}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Phone"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Email*
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={state.email}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Email"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Address*
|
||||
</label>
|
||||
<div className=" d-flex">
|
||||
<div><input
|
||||
type="text"
|
||||
name="Bname"
|
||||
value={state.Bname}
|
||||
className="mt-0 my-3 w-100 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Building Name*"
|
||||
/></div>
|
||||
<div> <input
|
||||
type="text"
|
||||
name="Sname"
|
||||
value={state.Sname}
|
||||
className="mt-0 ml-4 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Street Name*"
|
||||
/></div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<select
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
required
|
||||
name="country"
|
||||
value={state.country}
|
||||
// onChange={(e) => setCountry(e.target.value)}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="">Country*</option>
|
||||
{Country &&
|
||||
Country.getAllCountries().map((item) => (
|
||||
<option key={item.isoCode} value={item.isoCode}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
|
||||
|
||||
</select>
|
||||
<select
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
requiredname='city'
|
||||
name="city"
|
||||
value={state.city}
|
||||
// onChange={(e) => setCity(e.target.value)}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="">City*</option>
|
||||
{City &&
|
||||
|
||||
City.getCitiesOfCountry(state.country).map((item) => (
|
||||
<option key={item.isoCode} value={item.isoCode}>
|
||||
{item.name}
|
||||
{/* {console.log(item)} */}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group mb-30 width-100 row">
|
||||
<label className="my-3 col-md-4 control-label">
|
||||
Description
|
||||
</label>
|
||||
<div className="mt-0 col-md-10">
|
||||
<textarea
|
||||
value={state.description}
|
||||
onChange={handleChange}
|
||||
name="description"
|
||||
className="form-control input-field"
|
||||
rows="5"
|
||||
placeholder="Add description"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- Left Column Ends --> */}
|
||||
|
||||
{/* <!--Right Column Begins --> */}
|
||||
<div className=" col-lg-4">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Category*
|
||||
</label>
|
||||
|
||||
<select
|
||||
name="category"
|
||||
value={state.category}
|
||||
onChange={handleChange}
|
||||
className="form-control input-field"
|
||||
>
|
||||
<option value="">--select--</option>
|
||||
{categoryName && categoryName.map(item =>
|
||||
<option>{item?.name}</option>
|
||||
|
||||
)}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Status*
|
||||
</label>
|
||||
<select
|
||||
name="status"
|
||||
value={state.status}
|
||||
onChange={handleChange}
|
||||
className="form-control input-field"
|
||||
>
|
||||
<option value="">--select--</option>
|
||||
<option value={true}>Active</option>
|
||||
<option value={false}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Google Location
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="Glocation"
|
||||
value={state.Glocation}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Google Location(Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Linkedin URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="LinkedinUrl"
|
||||
value={state.LinkedinUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Linkedin URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Facebook URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="FacebookUrl"
|
||||
value={state.FacebookUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Facebook URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Instagram URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="InstagramUrl"
|
||||
value={state.InstagramUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Instagram URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!--Right Column Ends --> */}
|
||||
</div>
|
||||
<div className=" mt-4 row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
{/* <!-- End Page-content --> */}
|
||||
{/* <Footer /> */}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Add_Business
|
@ -1,292 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
|
||||
const Bisuness = () => {
|
||||
const [bisuness, setBisuness] = useState([])
|
||||
|
||||
|
||||
|
||||
const { token } = isAutheticated();
|
||||
|
||||
const getProducts = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/directory/getAll`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
// console.log(res.data.directory)
|
||||
setBisuness(res.data.directory)
|
||||
// changeState({
|
||||
// ...res.data,
|
||||
// pages: Math.ceil(res.data.totalProducts / limit),
|
||||
// });
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
getProducts();
|
||||
}, [getProducts]);
|
||||
|
||||
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
let status = window.confirm("Do you want to delete");
|
||||
if (!status) return;
|
||||
|
||||
let res = await axios.delete(`/api/directory/delete/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
// console.log(res)
|
||||
|
||||
if (res.data.success == true) {
|
||||
swal("success!", "Directory Deleted Successfully!", "success");
|
||||
window.location.reload();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const toggleStatus = async (id) => {
|
||||
let status = window.confirm("Do you want to delete");
|
||||
if (!status) {
|
||||
return;
|
||||
}
|
||||
let res = await axios.get(`/api/product/setStatus/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
if (res.status === 200) window.location.reload();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">Bisuness-Directory</h4>
|
||||
<Link to="/add_bisuness"><button type="button" className="btn btn-info float-end mb-3 ml-4"> + Add Bisuness</button></Link>
|
||||
{/* <div className="page-title-right">
|
||||
<ol className="breadcrumb m-0">
|
||||
<li className="breadcrumb-item">
|
||||
<Link to="/dashboard">Dating App</Link>
|
||||
</li>
|
||||
<li className="breadcrumb-item">Commerce - Products</li>
|
||||
</ol>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
{/* <div className="col-sm-12 col-md-6">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show{" "}
|
||||
<select
|
||||
onChange={(e) =>
|
||||
changeState({ limit: e.target.value, page: 1 })
|
||||
}
|
||||
className="select-w custom-select custom-select-sm form-control form-control-sm"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>{" "}
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div> */}
|
||||
{/* <div className="col-sm-12 col-md-6">
|
||||
<div className="dropdown d-block">
|
||||
<a href="/comproducts/add">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary add-btn waves-effect waves-light float-right"
|
||||
>
|
||||
<i className="fa fa-plus" aria-hidden="true"></i>{" "}
|
||||
Add New Product
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Category</th>
|
||||
<th>City</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{bisuness.map((item) =>
|
||||
|
||||
<tr>
|
||||
<td>{item?.name} </td>
|
||||
<td>{item?.category}</td>
|
||||
<td>{item?.city}</td>
|
||||
<td>
|
||||
<span
|
||||
className={`badge rounded-pill bg-${status ? "success" : "danger"
|
||||
} font-size-10`}
|
||||
>
|
||||
{status ? "Live" : "Suspended"}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
className={`btn btn-${status ? "danger" : "success"
|
||||
} btn-sm waves-effect waves-light btn-table ml-1`}
|
||||
onClick={() => toggleStatus('_id')}
|
||||
>
|
||||
{status ? "Suspend" : "Activate"}
|
||||
</button>
|
||||
<Link to={`/view_bisuness/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" mx-2 btn btn-info btn-sm waves-effect waves-light btn-table ml-1"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
<Link to={`/bisuness/edit/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" mx-2 btn btn-primary btn-sm waves-effect waves-light btn-table ml-1"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDelete(item._id)}
|
||||
className=" btn btn-danger btn-sm waves-effect waves-light btn-table ml-1"
|
||||
id="sa-params"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* <div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing{" "}
|
||||
{!totalProducts
|
||||
? totalProducts
|
||||
: page * limit - (limit - 1)}{" "}
|
||||
to{" "}
|
||||
{totalProducts > limit
|
||||
? limit * page > totalProducts
|
||||
? totalProducts
|
||||
: limit * page
|
||||
: totalProducts}{" "}
|
||||
of {totalProducts} entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div className="dataTables_paginate paging_simple_numbers float-right">
|
||||
<ul className="pagination">
|
||||
<li
|
||||
className={`paginate_button page-item previous ${page < 2 ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="0"
|
||||
tabIndex={page - 1}
|
||||
onClick={() => changeState({ page: page - 1 })}
|
||||
className="page-link"
|
||||
>
|
||||
Previous
|
||||
</button>
|
||||
</li>
|
||||
|
||||
{getTotalPages.map((pageNo) => {
|
||||
return (
|
||||
<li
|
||||
className={`paginate_button page-item ${pageNo === page ? "active" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
key={`page_no_${pageNo}`}
|
||||
value={pageNo}
|
||||
id={pageNo}
|
||||
aria-controls="datatable"
|
||||
data-dt-idx="1"
|
||||
tabIndex="0"
|
||||
className="page-link "
|
||||
onClick={() => changeState({ page: pageNo })}
|
||||
>
|
||||
{pageNo}
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
<li
|
||||
className={`paginate_button page-item next ${page === getTotalPages.length ? "disabled" : ""
|
||||
}`}
|
||||
>
|
||||
<button
|
||||
onClick={() => changeState({ page: page + 1 })}
|
||||
tabIndex={page + 1}
|
||||
className="page-link"
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Bisuness
|
@ -1,515 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import { Country, State, City } from "country-state-city";
|
||||
import swal from 'sweetalert';
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
const EditBisuness = () => {
|
||||
const [categoryName, setCategoryName] = useState([]);
|
||||
const { token } = isAutheticated();
|
||||
|
||||
let history = useHistory();
|
||||
const [state, setState] = useState({
|
||||
name: "",
|
||||
phone: "",
|
||||
email: "",
|
||||
Building_Name: "",
|
||||
Street_Name: "",
|
||||
country: "",
|
||||
city: "",
|
||||
loading: false,
|
||||
description: "",
|
||||
category: "",
|
||||
status: "",
|
||||
Glocation: "",
|
||||
LinkedinUrl: "",
|
||||
FacebookUrl: "",
|
||||
InstagramUrl: ""
|
||||
});
|
||||
|
||||
const { id } = useParams();
|
||||
// console.log(id)
|
||||
|
||||
const { description, loading } = state;
|
||||
|
||||
|
||||
const changeState = (newState) =>
|
||||
setState((prevState) => ({ ...prevState, ...newState }));
|
||||
|
||||
|
||||
|
||||
const handleChange = (e) => {
|
||||
changeState({ ...state, [e.target.name]: e.target.value })
|
||||
|
||||
};
|
||||
|
||||
|
||||
//category
|
||||
const fetchCategory = useCallback(async () => {
|
||||
const res = await axios.get(`/api/category/getAll`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
// console.log(res.data.category);
|
||||
setCategoryName(res.data.category)
|
||||
if (res.status === 200) changeState({ ...res.data });
|
||||
}, [token]);
|
||||
|
||||
useEffect(async () => {
|
||||
|
||||
fetchCategory();
|
||||
|
||||
}, [fetchCategory]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const fetchDirectory = useCallback(async () => {
|
||||
const res = await axios.get(`/api/directory/getOne/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
setState(res.data.directory)
|
||||
changeState({ loading: false });
|
||||
if (res.status === 200) changeState({ ...res.data });
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchDirectory();
|
||||
}, [fetchDirectory]);
|
||||
|
||||
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!(name || description || phone || email || Bname || Sname || city)) {
|
||||
alert("Please fill required field ");
|
||||
return;
|
||||
}
|
||||
changeState({ loading: true });
|
||||
|
||||
let res = await axios.put(
|
||||
`/api/directory/update/${id}`,
|
||||
{
|
||||
...state,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (res.status == 200) {
|
||||
changeState({ loading: false });
|
||||
swal("Edit Business successfully!");
|
||||
history.goBack()
|
||||
}
|
||||
};
|
||||
const onCancel = () => {
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// console.log(state)
|
||||
return (
|
||||
<>
|
||||
<div className=" main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="form-group text-right">
|
||||
<span className=" fs-2 text-xl-start font-weight-bold float-start">Edit Bisuness</span>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success mt-1 mb-0 my-1 btn btn-success btn-login waves-effect waves-light mr-1"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" mt-1 ml-2 btn btn-warning btn-cancel waves-effect waves-light mr-3"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- Save options Ends--> */}
|
||||
|
||||
{/* <!-- Row 1 Begins --> */}
|
||||
<div className="row">
|
||||
{/* <!--Left Column Begins--> */}
|
||||
<div className="col-lg-8">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
value={state.name}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
phone*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
name="phone"
|
||||
value={state.phone}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Phone"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Email*
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
value={state.email}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Email"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Address*
|
||||
</label>
|
||||
<div className=" d-flex">
|
||||
<div><input
|
||||
type="text"
|
||||
name="Building_Name"
|
||||
value={state.Building_Name}
|
||||
className="mt-0 my-3 w-100 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Building Name*"
|
||||
/></div>
|
||||
<div> <input
|
||||
type="text"
|
||||
name="Street_Name"
|
||||
value={state.Street_Name}
|
||||
className="mt-0 ml-4 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Street Name*"
|
||||
/></div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<select
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
required
|
||||
name="country"
|
||||
value={state.country}
|
||||
// onChange={(e) => setCountry(e.target.value)}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="">Country*</option>
|
||||
{Country &&
|
||||
Country.getAllCountries().map((item) => (
|
||||
<option key={item.isoCode} value={item.isoCode}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
|
||||
|
||||
</select>
|
||||
<select
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
requiredname='city'
|
||||
name="city"
|
||||
value={state.city}
|
||||
// onChange={(e) => setCity(e.target.value)}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="">City*</option>
|
||||
{City &&
|
||||
|
||||
City.getCitiesOfCountry(state.country).map((item) => (
|
||||
<option key={item.isoCode} value={item.isoCode}>
|
||||
{item.name}
|
||||
{/* {console.log(item)} */}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group mb-30 width-100 row">
|
||||
<label className="my-3 col-md-4 control-label">
|
||||
Description
|
||||
</label>
|
||||
<div className="mt-0 col-md-10">
|
||||
<textarea
|
||||
value={state.description}
|
||||
onChange={handleChange}
|
||||
name="description"
|
||||
className="form-control input-field"
|
||||
rows="5"
|
||||
placeholder="Add description"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- Left Column Ends --> */}
|
||||
|
||||
{/* <!--Right Column Begins --> */}
|
||||
<div className=" col-lg-4">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Category*
|
||||
</label>
|
||||
<select
|
||||
name="category"
|
||||
value={state.category}
|
||||
onChange={handleChange}
|
||||
className="form-control input-field"
|
||||
>
|
||||
<option value="">--select--</option>
|
||||
{categoryName && categoryName.map(item =>
|
||||
<option>{item?.name}</option>
|
||||
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Status*
|
||||
</label>
|
||||
<select
|
||||
name="status"
|
||||
value={state.status}
|
||||
onChange={handleChange}
|
||||
className="form-control input-field"
|
||||
>
|
||||
<option value="">--select--</option>
|
||||
<option value={true}>Active</option>
|
||||
<option value={false}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Google Location
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="Glocation"
|
||||
value={state.Glocation}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Google Location(Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Linkedin URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="LinkedinUrl"
|
||||
value={state.LinkedinUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Linkedin URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Facebook URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="FacebookUrl"
|
||||
value={state.FacebookUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Facebook URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100"
|
||||
>
|
||||
Instagram URL
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="InstagramUrl"
|
||||
value={state.InstagramUrl}
|
||||
className="mt-0 my-3 form-control input-field"
|
||||
onChange={handleChange}
|
||||
placeholder="Instagram URL (Optional)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!--Right Column Ends --> */}
|
||||
</div>
|
||||
<div className=" mt-4 row">
|
||||
{/* <!--Left Column Begins--> */}
|
||||
{/* <div className="col-lg-8">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<form className="">
|
||||
<div className="row">
|
||||
<div className="col-lg-4">
|
||||
<div className=" form-group">
|
||||
<label
|
||||
htmlFor=" basicpill-phoneno-input"
|
||||
className=" label-100"
|
||||
>
|
||||
Price*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="price"
|
||||
value={price}
|
||||
onChange={handleChange}
|
||||
className="form-control input-field"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
{/* <!-- Left Column Ends --> */}
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
{/* <!-- End Page-content --> */}
|
||||
{/* <Footer /> */}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditBisuness
|
@ -1,134 +0,0 @@
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import { useParams } from "react-router-dom";
|
||||
const View_Bisuness = () => {
|
||||
const { id } = useParams();
|
||||
// console.log(id)
|
||||
const [bisuness, setBisuness] = useState([])
|
||||
|
||||
|
||||
// const { products, page, limit, totalProducts, pages } = state;
|
||||
|
||||
|
||||
const { token } = isAutheticated();
|
||||
|
||||
const view_business = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/directory/getOne/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log(res.data.directory.name)
|
||||
setBisuness(res.data.directory)
|
||||
// changeState({
|
||||
// ...res.data,
|
||||
// pages: Math.ceil(res.data.totalProducts / limit),
|
||||
// });
|
||||
// limit, page,
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
view_business();
|
||||
}, [view_business]);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">View Bisuness</h4>
|
||||
{/* <Link to="/add_bisuness"><button type="button" className="btn btn-info float-end mb-3 ml-4"> View Bisuness</button></Link> */}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Category</th>
|
||||
<th>email</th>
|
||||
<th>phone</th>
|
||||
<th>Building_Name</th>
|
||||
<th>Street_Name</th>
|
||||
<th>city</th>
|
||||
<th>description</th>
|
||||
<th>Status</th>
|
||||
<th>Google Location</th>
|
||||
<th>LinkedinUrl</th>
|
||||
<th>FacebookUrl</th>
|
||||
<th>intagramUrl</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>{bisuness?.name} </td>
|
||||
<td>{bisuness?.category}</td>
|
||||
<td>{bisuness?.email}</td>
|
||||
<td>{bisuness?.phone}</td>
|
||||
<td>{bisuness?.Building_Name}</td>
|
||||
<td>{bisuness?.Street_Name}</td>
|
||||
<td>{bisuness?.city}</td>
|
||||
<td>{bisuness?.description}</td>
|
||||
|
||||
<td>
|
||||
<span
|
||||
className={`badge rounded-pill bg-${bisuness?.status ? "success" : "danger"
|
||||
} font-size-10`}
|
||||
>
|
||||
{bisuness?.status ? "Live" : "Suspended"}
|
||||
</span>
|
||||
</td>
|
||||
<td>{bisuness?.Glocation}</td>
|
||||
<td>{bisuness?.LinkedinUrl}</td>
|
||||
<td>{bisuness?.FacebookUrl}</td>
|
||||
<td>{bisuness?.InstagramUrl}</td>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default View_Bisuness
|
@ -1,149 +0,0 @@
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
CCol,
|
||||
CContainer,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CInputGroup,
|
||||
CInputGroupText,
|
||||
CRow,
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilPencil, cilSettings, cilLockLocked, cilUser } from '@coreui/icons'
|
||||
const AddNews = () => {
|
||||
const { token } = isAutheticated();
|
||||
let history = useHistory();
|
||||
const [image, setImage] = useState("");
|
||||
const [title, setTitle] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const myForm = new FormData();
|
||||
|
||||
myForm.set("title", title);
|
||||
myForm.set("description", description);
|
||||
myForm.set("image", image);
|
||||
setLoading({ loading: true });
|
||||
// console.log(image)
|
||||
let res = await axios.post(
|
||||
`/api/news/create`, myForm,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": 'multipart/form-data',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log(res.data)
|
||||
if (res.data) {
|
||||
swal("success!", "News Added Successfully!", "success");
|
||||
history.goBack();
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleImage = (e) => {
|
||||
const files = e.target.files[0];
|
||||
// console.log(files)
|
||||
setImage(files);
|
||||
|
||||
};
|
||||
//
|
||||
const onCancel = () => {
|
||||
// window.location = "/comproducts";
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-light min-vh-70 d-flex flex-row ">
|
||||
<CContainer>
|
||||
<CRow className="align-left w-140">
|
||||
<CCol md={19} lg={27} xl={16}>
|
||||
<CCard className="mx-4">
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h3 className="mb-4 justify-content-center">Add News</h3>
|
||||
<div>
|
||||
<div>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilPencil} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
value={title}
|
||||
placeholder="Title" />
|
||||
</CInputGroup>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilSettings} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
value={description}
|
||||
placeholder="Description" />
|
||||
</CInputGroup>
|
||||
|
||||
<CInputGroup className="mb-3">
|
||||
|
||||
{/* <CIcon icon={cilLockLocked} /> */}
|
||||
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
</CInputGroup>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success btn-login waves-effect waves-light"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" ml-2 btn btn-warning btn-cancel waves-effect waves-light"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CContainer>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddNews
|
@ -1,165 +0,0 @@
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
CCol,
|
||||
CContainer,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CInputGroup,
|
||||
CInputGroupText,
|
||||
CRow,
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilPencil, cilSettings, cilLockLocked, cilUser } from '@coreui/icons'
|
||||
const EditNews = () => {
|
||||
const { id } = useParams();
|
||||
// console.log(id)
|
||||
const { token } = isAutheticated();
|
||||
let history = useHistory();
|
||||
const [image, setImage] = useState("");
|
||||
const [title, setTitle] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
//fetch one image
|
||||
useEffect(async () => {
|
||||
const res = await axios.get(`/api/news/getOne/${id}`, {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
});
|
||||
// console.log(res.data.news.title)
|
||||
setTitle(res.data.news.title)
|
||||
setDescription(res.data.news.description)
|
||||
|
||||
}, [id]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const myForm = new FormData();
|
||||
|
||||
myForm.set("title", title);
|
||||
myForm.set("description", description);
|
||||
myForm.set("image", image);
|
||||
setLoading({ loading: true });
|
||||
// console.log(image)
|
||||
let res = await axios.put(
|
||||
`/api/news/update/${id}`, myForm,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": 'multipart/form-data',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
// console.log(res.data)
|
||||
if (res.data) {
|
||||
swal("success!", "News Edit Successfully!", "success");
|
||||
history.goBack();
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleImage = (e) => {
|
||||
const files = e.target.files[0];
|
||||
// console.log(files)
|
||||
setImage(files);
|
||||
|
||||
};
|
||||
//
|
||||
const onCancel = () => {
|
||||
// window.location = "/comproducts";
|
||||
history.goBack()
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-light min-vh-70 d-flex flex-row ">
|
||||
<CContainer>
|
||||
<CRow className="align-left w-140">
|
||||
<CCol md={19} lg={27} xl={16}>
|
||||
<CCard className="mx-4">
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h3 className="mb-4 justify-content-center">Edit News</h3>
|
||||
<div>
|
||||
<div>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilPencil} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
value={title}
|
||||
placeholder="Title" />
|
||||
</CInputGroup>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilSettings} />
|
||||
</CInputGroupText>
|
||||
<CFormInput type="text"
|
||||
required
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
value={description}
|
||||
placeholder="Description" />
|
||||
</CInputGroup>
|
||||
|
||||
<CInputGroup className="mb-3">
|
||||
|
||||
{/* <CIcon icon={cilLockLocked} /> */}
|
||||
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
</CInputGroup>
|
||||
</div>
|
||||
|
||||
<div className=" d-flex">
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
type="button"
|
||||
className="btn btn-success btn-login waves-effect waves-light"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Save"}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
type="button"
|
||||
className=" ml-2 btn btn-warning btn-cancel waves-effect waves-light"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</CCol>
|
||||
</CRow>
|
||||
</CContainer>
|
||||
</div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditNews
|
@ -1,164 +0,0 @@
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
|
||||
function News() {
|
||||
const [news, setNews] = useState([])
|
||||
|
||||
const { token } = isAutheticated();
|
||||
|
||||
const getNews = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/news/getAll`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
setNews(res.data.news)
|
||||
|
||||
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
getNews();
|
||||
}, [getNews]);
|
||||
|
||||
|
||||
const handleDelete = async (id) => {
|
||||
let status = window.confirm("Do you want to delete");
|
||||
if (!status) return;
|
||||
|
||||
let res = await axios.delete(`/api/news/delete/${id}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
console.log(res)
|
||||
if (res.data.success == true) {
|
||||
swal("success!", "News Deleted Successfully!", "success");
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//change time formate
|
||||
function formatAMPM(date) {
|
||||
var hours = new Date(date).getHours();
|
||||
var minutes = new Date(date).getMinutes();
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">CMP-News</h4>
|
||||
<Link to="/addNews"><button type="button" className="btn btn-info float-end mb-3 ml-4"> + Add News</button></Link>
|
||||
{/* <div className="page-title-right">
|
||||
<ol className="breadcrumb m-0">
|
||||
<li className="breadcrumb-item">
|
||||
<Link to="/dashboard">CMD-App</Link>
|
||||
</li>
|
||||
<li className="breadcrumb-item">CMD-Category</li>
|
||||
</ol>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Image</th>
|
||||
<th>Added On</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{news && news.map((item, index) =>
|
||||
<tr>
|
||||
<td>{item?.title}</td>
|
||||
<td>
|
||||
<img src={`${item?.image.url}`} width="50" alt="" /></td>
|
||||
<td>
|
||||
{/* {item?.addedOn} */}
|
||||
{new Date(`${item?.addedOn}`).toDateString()}<span> , {`${formatAMPM(item?.addedOn)}`}</span>
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
<td>
|
||||
<Link to={`/news/view/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" mx-2 btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</Link>
|
||||
<Link to={`/news/edit/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className=" mx-2 btn btn-primary btn-sm waves-effect waves-light btn-table ml-2"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDelete(`${item._id}`)}
|
||||
className=" btn btn-danger btn-sm waves-effect waves-light btn-table ml-2"
|
||||
id="sa-params"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default News;
|
298
src/views/Products/AddProduct.js
Normal file
298
src/views/Products/AddProduct.js
Normal file
@ -0,0 +1,298 @@
|
||||
|
||||
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
// import { WebsiteURL } from '../WebsiteURL'
|
||||
|
||||
const AddProduct = () => {
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [data, setData] = useState({
|
||||
image: '',
|
||||
imageURL: '',
|
||||
name: '',
|
||||
description: '',
|
||||
|
||||
base_Price: '',
|
||||
price_Level_2: '',
|
||||
price_Level_3: ''
|
||||
|
||||
})
|
||||
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
const handleChange = (e) => {
|
||||
|
||||
if (e.target.id === 'image') {
|
||||
if (
|
||||
e.target.files[0]?.type === 'image/jpeg' ||
|
||||
e.target.files[0]?.type === 'image/png' ||
|
||||
e.target.files[0]?.type === 'image/jpg'
|
||||
) {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: URL.createObjectURL(e.target.files[0]),
|
||||
image: e.target.files[0],
|
||||
}))
|
||||
return
|
||||
} else {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Upload jpg, jpeg, png only.',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: '',
|
||||
image: '',
|
||||
}))
|
||||
e.target.value = null
|
||||
return
|
||||
}
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (
|
||||
data.name.trim() === '' ||
|
||||
|
||||
data.description.trim() === '' ||
|
||||
data.base_Price === '' ||
|
||||
data.price_Level_2 === '' ||
|
||||
data.price_Level_3 === '' ||
|
||||
data.imageURL.trim() === ''
|
||||
) {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
const formData = new FormData()
|
||||
formData.set('name', data.name)
|
||||
|
||||
formData.set('description', data.description)
|
||||
formData.set('base_Price', data.base_Price)
|
||||
formData.set('price_Level_2', data.price_Level_2)
|
||||
formData.set('price_Level_3', data.price_Level_3)
|
||||
formData.append('image', data.image)
|
||||
|
||||
|
||||
axios
|
||||
.post(`/api/product/create/`, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Added',
|
||||
text: 'Product added successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/products', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
const message = err.response?.data?.message || 'Something went wrong!'
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: message,
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Add Product
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Save'}
|
||||
</Button>
|
||||
<Link to="/products">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Product Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={data.name}
|
||||
maxLength={25}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
{data.name ? <><small className="charLeft mt-4 fst-italic">
|
||||
{25 - data.name.length} characters left
|
||||
</small></> : <></>
|
||||
|
||||
} </div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Description*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="description"
|
||||
value={data.description}
|
||||
maxLength="100"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
{data.description ? <><small className="charLeft mt-4 fst-italic">
|
||||
{100 - data.description.length} characters left
|
||||
</small></> : <></>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="image" className="form-label">
|
||||
Product Image*
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
className="form-control"
|
||||
id="image"
|
||||
accept="image/*"
|
||||
multiple
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Upload jpg, jpeg and png only*</p>
|
||||
</div>
|
||||
<div className="mb-3" style={{ height: '200px', maxWdth: '100%' }}>
|
||||
<img
|
||||
src={data.imageURL}
|
||||
alt="Uploaded Image will be shown here"
|
||||
style={{ maxHeight: '200px', maxWidth: '100%' }}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Base Price*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="base_Price"
|
||||
value={data.base_Price}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Price Level 2*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="price_Level_2"
|
||||
value={data.price_Level_2}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Price Level 3*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="price_Level_3"
|
||||
value={data.price_Level_3}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddProduct
|
333
src/views/Products/EditProduct.js
Normal file
333
src/views/Products/EditProduct.js
Normal file
@ -0,0 +1,333 @@
|
||||
|
||||
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
// import { WebsiteURL } from '../WebsiteURL'
|
||||
|
||||
const EditProduct = () => {
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const id = useParams()?.id
|
||||
const [data, setData] = useState({
|
||||
image: '',
|
||||
imageURL: '',
|
||||
name: '',
|
||||
description: '',
|
||||
|
||||
base_Price: '',
|
||||
price_Level_2: '',
|
||||
price_Level_3: ''
|
||||
|
||||
})
|
||||
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
//get Productdata
|
||||
const getProduct = async () => {
|
||||
|
||||
axios
|
||||
.get(`/api/product/getOne/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
...res.data?.product,
|
||||
imageURL: res.data?.product?.image?.url,
|
||||
}))
|
||||
})
|
||||
.catch((err) => { })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getProduct()
|
||||
}, [])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const handleChange = (e) => {
|
||||
|
||||
if (e.target.id === 'image') {
|
||||
if (
|
||||
e.target.files[0]?.type === 'image/jpeg' ||
|
||||
e.target.files[0]?.type === 'image/png' ||
|
||||
e.target.files[0]?.type === 'image/jpg'
|
||||
) {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: URL.createObjectURL(e.target.files[0]),
|
||||
image: e.target.files[0],
|
||||
}))
|
||||
return
|
||||
} else {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Upload jpg, jpeg, png only.',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: '',
|
||||
image: '',
|
||||
}))
|
||||
e.target.value = null
|
||||
return
|
||||
}
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (
|
||||
data.name.trim() === '' ||
|
||||
|
||||
data.description.trim() === '' ||
|
||||
data.base_Price === '' ||
|
||||
data.price_Level_2 === '' ||
|
||||
data.price_Level_3 === '' ||
|
||||
data.imageURL.trim() === ''
|
||||
) {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
const formData = new FormData()
|
||||
formData.set('name', data.name)
|
||||
|
||||
formData.set('description', data.description)
|
||||
formData.set('base_Price', data.base_Price)
|
||||
formData.set('price_Level_2', data.price_Level_2)
|
||||
formData.set('price_Level_3', data.price_Level_3)
|
||||
formData.append('image', data.image)
|
||||
|
||||
|
||||
axios
|
||||
.put(`/api//product/update/${id}`, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Added',
|
||||
text: 'Product Edited successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/products', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
const message = err.response?.data?.message || 'Something went wrong!'
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: message,
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
console.log(data)
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Edit Product
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Save'}
|
||||
</Button>
|
||||
<Link to="/products">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Product Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={data.name}
|
||||
maxLength={25}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
{data.name ? <><small className="charLeft mt-4 fst-italic">
|
||||
{25 - data.name.length} characters left
|
||||
</small></> : <></>
|
||||
|
||||
} </div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Description*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="description"
|
||||
value={data.description}
|
||||
maxLength="100"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
{data.description ? <><small className="charLeft mt-4 fst-italic">
|
||||
{100 - data.description.length} characters left
|
||||
</small></> : <></>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="image" className="form-label">
|
||||
Product Image*
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
className="form-control"
|
||||
id="image"
|
||||
accept="image/*"
|
||||
multiple
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Upload jpg, jpeg and png only*</p>
|
||||
</div>
|
||||
<div className="mb-3" style={{ height: '200px', maxWdth: '100%' }}>
|
||||
<img
|
||||
src={data.imageURL}
|
||||
alt="Uploaded Image will be shown here"
|
||||
style={{ maxHeight: '200px', maxWidth: '100%' }}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-lg-6 col-md-6 col-sm-12 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Base Price*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="base_Price"
|
||||
value={data.base_Price}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Price Level 2*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="price_Level_2"
|
||||
value={data.price_Level_2}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Price Level 3*
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
className="form-control"
|
||||
id="price_Level_3"
|
||||
value={data.price_Level_3}
|
||||
onChange={(e) => handleChange(e)}
|
||||
|
||||
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditProduct
|
371
src/views/Products/Products.js
Normal file
371
src/views/Products/Products.js
Normal file
@ -0,0 +1,371 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
const Products = () => {
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [success, setSuccess] = useState(true)
|
||||
const [productsData, setProductsData] = useState([])
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1)
|
||||
const [itemPerPage, setItemPerPage] = useState(10)
|
||||
const [showData, setShowData] = useState(productsData)
|
||||
|
||||
const handleShowEntries = (e) => {
|
||||
setCurrentPage(1)
|
||||
setItemPerPage(e.target.value)
|
||||
}
|
||||
|
||||
|
||||
|
||||
const getProductsData = async () => {
|
||||
axios
|
||||
.get(`/api/product/getAll/`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setProductsData(res.data?.product)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getProductsData()
|
||||
}, [success])
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = () => {
|
||||
const indexOfLastPost = currentPage * itemPerPage
|
||||
const indexOfFirstPost = indexOfLastPost - itemPerPage
|
||||
setShowData(productsData.slice(indexOfFirstPost, indexOfLastPost))
|
||||
}
|
||||
loadData()
|
||||
}, [currentPage, itemPerPage, productsData])
|
||||
|
||||
const handleDelete = (id) => {
|
||||
swal({
|
||||
title: 'Are you sure?',
|
||||
icon: 'error',
|
||||
buttons: { Yes: { text: 'Yes', value: true }, Cancel: { text: 'Cancel', value: 'cancel' } },
|
||||
}).then((value) => {
|
||||
if (value === true) {
|
||||
axios
|
||||
.delete(`/api/product/delete/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setSuccess((prev) => !prev)
|
||||
})
|
||||
.catch((err) => {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Products
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate('/product/add', { replace: true })
|
||||
}}
|
||||
>
|
||||
Add Product
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: '10%' }}
|
||||
name=""
|
||||
onChange={(e) => handleShowEntries(e)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: '1px solid' }}
|
||||
>
|
||||
<thead className="thead-info" style={{ background: 'rgb(140, 213, 213)' }}>
|
||||
<tr>
|
||||
|
||||
<th className="text-start">Product Name</th>
|
||||
<th className="text-start">Thumbnail</th>
|
||||
<th className="text-start">Base Price</th>
|
||||
<th className="text-start">Added On</th>
|
||||
<th className="text-start">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && showData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="6">
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="6">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
showData.map((product, i) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td className="text-start">{product.name}</td>
|
||||
<th>
|
||||
{product?.image && (
|
||||
<>
|
||||
<img src={product.image?.url} width="50" alt="preview" />
|
||||
</>
|
||||
)}
|
||||
</th>
|
||||
<th className="text-start">₹{product.base_Price}</th>
|
||||
<td className="text-start">
|
||||
{new Date(product.createdAt).toLocaleString('en-IN', {
|
||||
weekday: 'short',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true,
|
||||
})}
|
||||
</td>
|
||||
<td className="text-start">
|
||||
|
||||
<Link to={`/product/view/${product._id}`}>
|
||||
<button
|
||||
style={{ color: 'white', marginRight: '1rem' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mx-1
|
||||
mt-1
|
||||
"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</Link>
|
||||
<Link to={`/product/edit/${product._id}`}>
|
||||
<button
|
||||
style={{ color: 'white', marginRight: '1rem' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-info btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mt-1
|
||||
mx-1
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<Link
|
||||
to={'#'}
|
||||
style={{
|
||||
marginRight: '1rem',
|
||||
}}
|
||||
>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-danger btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
mt-1
|
||||
mx-1
|
||||
|
||||
"
|
||||
onClick={() => {
|
||||
handleDelete(product._id)
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{' '}
|
||||
{Math.min(currentPage * itemPerPage, productsData.length)} of{' '}
|
||||
{productsData.length} entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div className="d-flex">
|
||||
<ul className="pagination ms-auto">
|
||||
<li
|
||||
className={
|
||||
currentPage === 1
|
||||
? 'paginate_button page-item previous disabled'
|
||||
: 'paginate_button page-item previous'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
Previous
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(currentPage - 1 < 1) && (
|
||||
<li className="paginate_button page-item">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
{currentPage - 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li className="paginate_button page-item active">
|
||||
<span className="page-link" style={{ cursor: 'pointer' }}>
|
||||
{currentPage}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
productsData.length - 1
|
||||
) && (
|
||||
<li className="paginate_button page-item ">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setCurrentPage((prev) => prev + 1)
|
||||
}}
|
||||
>
|
||||
{currentPage + 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li
|
||||
className={
|
||||
!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
productsData.length - 1
|
||||
)
|
||||
? 'paginate_button page-item next'
|
||||
: 'paginate_button page-item next disabled'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev + 1)}
|
||||
>
|
||||
Next
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Products
|
@ -1,35 +1,35 @@
|
||||
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import swal from 'sweetalert';
|
||||
// import { API } from "../../data";
|
||||
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { isAutheticated } from "../../auth";
|
||||
import { isAutheticated } from "src/auth";
|
||||
|
||||
function ViewNews() {
|
||||
const [news, setNews] = useState([])
|
||||
function ViewProduct() {
|
||||
const [product, setProduct] = useState([])
|
||||
const { id } = useParams();
|
||||
console.log(id)
|
||||
const { token } = isAutheticated();
|
||||
const token = isAutheticated();
|
||||
|
||||
const getNews = useCallback(async () => {
|
||||
const getProduct = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/news/getOne/${id}`,
|
||||
`/api/product/getOne/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log(res.data.news)
|
||||
setNews(res.data.news)
|
||||
console.log(res.data.product)
|
||||
setProduct(res.data.product)
|
||||
|
||||
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
getNews();
|
||||
}, [getNews]);
|
||||
getProduct();
|
||||
}, [getProduct]);
|
||||
|
||||
|
||||
|
||||
@ -56,8 +56,8 @@ function ViewNews() {
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">CMP-News</h4>
|
||||
<Link to="/addNews"><button type="button" className="btn btn-info float-end mb-3 ml-4"> + Add News</button></Link>
|
||||
<h4 className="mb-3">Product</h4>
|
||||
<Link to="/product/add"><button type="button" className="btn btn-info float-end mb-3 ml-4"> + Add Product</button></Link>
|
||||
{/* <div className="page-title-right">
|
||||
<ol className="breadcrumb m-0">
|
||||
<li className="breadcrumb-item">
|
||||
@ -81,36 +81,33 @@ function ViewNews() {
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Title</th>
|
||||
|
||||
<th>Image</th>
|
||||
<th>Description</th>
|
||||
<th>Added On</th>
|
||||
<th>Updated At</th>
|
||||
<tr><th>Id</th> <td>{product?._id}</td></tr>
|
||||
<tr><th>Name</th> <td>{product?.name}</td></tr>
|
||||
|
||||
<tr><th>image</th><td>
|
||||
<img src={`${product.image?.url}`} width="50" alt="" />
|
||||
</td></tr>
|
||||
<tr><th>Description</th><td>{product?.description}</td></tr>
|
||||
<tr><th>Base Price</th><td>{product?.base_Price}</td></tr>
|
||||
<tr><th>Price Level 2</th><td>{product?.price_Level_2}</td></tr>
|
||||
|
||||
<tr><th>Price Level 3</th><td>{product?.price_Level_3}</td></tr>
|
||||
|
||||
{/* <tr><th>Product Time</th><td>{product?.time}</td></tr>
|
||||
<tr><th>Location</th><td>{product?.location}</td></tr> */}
|
||||
<tr><th>Created On</th><td>
|
||||
{new Date(`${product?.createdAt}`).toDateString()}<span> , {`${formatAMPM(product?.createdAt)}`}</span>
|
||||
</td></tr>
|
||||
<tr><th>Updated At</th>
|
||||
<td>
|
||||
{new Date(`${product?.updatedAt}`).toDateString()}<span> , {`${formatAMPM(product?.updatedAt)}`}</span>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
{news &&
|
||||
<tr>
|
||||
<td>{news?._id}</td>
|
||||
<td>{news?.title}</td>
|
||||
<td>
|
||||
<img src={`${news.image?.url}`} width="50" alt="" />
|
||||
</td>
|
||||
|
||||
<td>{news?.description}</td>
|
||||
<td>
|
||||
{new Date(`${news?.addedOn}`).toDateString()}<span> , {`${formatAMPM(news?.addedOn)}`}</span>
|
||||
</td>
|
||||
<td>
|
||||
{new Date(`${news?.updatedAt}`).toDateString()}<span> , {`${formatAMPM(news?.updatedAt)}`}</span>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -128,4 +125,4 @@ function ViewNews() {
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewNews;
|
||||
export default ViewProduct;
|
@ -1,66 +1,127 @@
|
||||
import React from 'react'
|
||||
import { CForm, CCol, CFormLabel, CContainer, CRow, CCardGroup, CCard, CCardBody, CFormInput, CFormSelect, CFormCheck, CButton } from '@coreui/react'
|
||||
import { Country, City } from 'country-state-city'
|
||||
import { CForm, CCol, CFormLabel, CContainer, CRow, CCardGroup, CCard, CCardBody, CFormInput, CButton } from '@coreui/react'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import axios from 'axios'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
const EditProfile = () => {
|
||||
const [cities, setCities] = useState([])
|
||||
const { token } = isAutheticated()
|
||||
const [ownerDetails, setOwnerDetails] = useState({
|
||||
cafeName: '',
|
||||
email: '',
|
||||
location: '',
|
||||
country: 'India',
|
||||
city: ''
|
||||
})
|
||||
const history = useHistory()
|
||||
const [processing, setProcessing] = useState(false)
|
||||
const countries = Country.getAllCountries()
|
||||
useEffect(() => {
|
||||
const countryCode = countries.find(item => item.name === ownerDetails.country)
|
||||
setCities(() => City.getCitiesOfCountry(countryCode?.isoCode))
|
||||
getData()
|
||||
|
||||
}, [ownerDetails.country])
|
||||
const EditProfile = () => {
|
||||
|
||||
const [image, setImage] = useState("");
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [imagesPreview, setImagesPreview] = useState();
|
||||
const token = isAutheticated()
|
||||
|
||||
const [ownerDetails, setOwnerDetails] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
phone: ''
|
||||
|
||||
})
|
||||
const history = useNavigate()
|
||||
|
||||
|
||||
|
||||
const getData = async () => {
|
||||
let res = await axios.get('/owner', {
|
||||
let res = await axios.get(`/api/v1/user/details`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
if (res) {
|
||||
if (res.data.success) {
|
||||
|
||||
setOwnerDetails({ ...res.data.user })
|
||||
|
||||
if (res.data.user.avatar) {
|
||||
setImagesPreview(res.data.user.avatar.url)
|
||||
}
|
||||
}
|
||||
console.log(ownerDetails);
|
||||
|
||||
|
||||
|
||||
}
|
||||
const handleChange = (event) => {
|
||||
const { name, value } = event.target;
|
||||
setOwnerDetails({ ...ownerDetails, [name]: value });
|
||||
};
|
||||
|
||||
const handleImage = (e) => {
|
||||
const files = e.target.files[0];
|
||||
|
||||
// console.log(files)
|
||||
setImage(files);
|
||||
// only for file preview------------------------------------
|
||||
const Reader = new FileReader();
|
||||
Reader.readAsDataURL(files);
|
||||
|
||||
Reader.onload = () => {
|
||||
if (Reader.readyState === 2) {
|
||||
setImagesPreview(Reader.result);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
};
|
||||
async function handleSubmit() {
|
||||
|
||||
let res = await axios.put(`/owner`, ownerDetails, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
}
|
||||
if (ownerDetails.name === '' || ownerDetails.email === '' || ownerDetails.phone === '') {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
setProcessing(true)
|
||||
console.log(res.data);
|
||||
return
|
||||
}
|
||||
const formData = new FormData()
|
||||
formData.append('name', ownerDetails.name)
|
||||
formData.append('email', ownerDetails.email)
|
||||
formData.append('phone', ownerDetails.phone)
|
||||
formData.append('avatar', image)
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await axios
|
||||
.put(`/api/v1/user/update/profile`, formData, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
},
|
||||
})
|
||||
if (res.data.success === true) {
|
||||
|
||||
if (res) {
|
||||
// localStorage.setItem("auth", JSON.stringify({
|
||||
setLoading(false)
|
||||
swal({
|
||||
title: 'Edited',
|
||||
text: 'Profile Edited Successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
history(-1)
|
||||
|
||||
// token: res.data.token,
|
||||
// }));
|
||||
history.push('/profile')
|
||||
}
|
||||
} catch (error) {
|
||||
const message = error?.response?.data?.message || 'Something went wrong!'
|
||||
setLoading(false)
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: message,
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
const handleCancle = () => {
|
||||
history.push('/dashboard')
|
||||
}
|
||||
useEffect(() => {
|
||||
|
||||
getData()
|
||||
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div >
|
||||
@ -70,49 +131,46 @@ const EditProfile = () => {
|
||||
<CCol md={8} className='mt-5'>
|
||||
<CCardGroup>
|
||||
<CCard className="p-4">
|
||||
|
||||
<h2 >Edit Profile</h2>
|
||||
<CCardBody>
|
||||
<h1 >Edit Profile</h1>
|
||||
|
||||
<CForm className="row g-3">
|
||||
<CCol xs={12}>
|
||||
<CFormLabel htmlFor="inputAddress">Cafe Name</CFormLabel>
|
||||
<CFormInput id="inputAddress" placeholder="" name='cafeName' value={ownerDetails.cafeName} onChange={handleChange} />
|
||||
<CFormLabel htmlFor="inputAddress">Name *</CFormLabel>
|
||||
<CFormInput id="inputAddress" placeholder="" name='name' value={ownerDetails.name} onChange={handleChange} />
|
||||
</CCol>
|
||||
|
||||
<CCol md={6}>
|
||||
<CFormLabel htmlFor="inputEmail4">Email</CFormLabel>
|
||||
<CFormLabel htmlFor="inputEmail4">Email *</CFormLabel>
|
||||
<CFormInput type="email" id="inputEmail4" name='email' value={ownerDetails.email} onChange={handleChange} />
|
||||
</CCol>
|
||||
{/* <CCol md={6}>
|
||||
<CFormLabel htmlFor="inputPassword4">Password</CFormLabel>
|
||||
<CFormInput type="password" id="inputPassword4" name='password' value={ownerDetails.password} onChange={handleChange} />
|
||||
</CCol> */}
|
||||
|
||||
|
||||
<CCol md={12}>
|
||||
<CFormLabel htmlFor="inputCity">Location</CFormLabel>
|
||||
<CFormInput id="inputCity" name='location' value={ownerDetails.location} onChange={handleChange} />
|
||||
</CCol>
|
||||
<CCol md={6}>
|
||||
<CFormLabel htmlFor="inputState">Country</CFormLabel>
|
||||
<CFormSelect id="inputState" name='country' onChange={handleChange}>
|
||||
<option>Select a country</option>
|
||||
{countries.map(item => <option value={item.name}>{item.name}</option>)}
|
||||
|
||||
</CFormSelect>
|
||||
</CCol>
|
||||
<CCol md={6}>
|
||||
<CFormLabel htmlFor="inputState">City</CFormLabel>
|
||||
<CFormSelect id="inputState" name='city' onChange={handleChange}>
|
||||
<option>Select a city</option>
|
||||
{cities.map(item => <option value={item.name}>{item.name}</option>)}
|
||||
|
||||
</CFormSelect>
|
||||
<CFormLabel htmlFor="inputPassword4">Phone *</CFormLabel>
|
||||
<CFormInput type="number" id="inputPassword4" minLength={8} name='phone' value={ownerDetails.phone} onChange={handleChange} />
|
||||
</CCol>
|
||||
|
||||
|
||||
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
<div id="createProductFormImage" className="w-50 d-flex">
|
||||
|
||||
{imagesPreview && <img className=" w-50 p-1 " src={imagesPreview} alt="Product Preview" />}
|
||||
|
||||
</div>
|
||||
<CCol xs={12}>
|
||||
<CButton onClick={handleSubmit} color='dark'>Submit</CButton>
|
||||
<CButton onClick={handleSubmit} color='primary'>{loading ? 'Loading...' : 'Submit'}</CButton>
|
||||
<CButton className='ml-2' onClick={handleCancle} color='warning'>Cancel</CButton>
|
||||
|
||||
</CCol>
|
||||
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
|
@ -1,7 +1,13 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
CCol,
|
||||
CForm,
|
||||
CFormInput,
|
||||
CFormLabel,
|
||||
CFormSelect,
|
||||
CRow,
|
||||
CTable,
|
||||
CTableBody,
|
||||
@ -13,13 +19,13 @@ import {
|
||||
import { useState } from 'react'
|
||||
import axios from 'axios';
|
||||
import { isAutheticated } from 'src/auth';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
const Profile = () => {
|
||||
// const user = JSON.parse(localStorage.getItem('auth')).user
|
||||
const [user, setUser] = useState({});
|
||||
const { token } = isAutheticated();
|
||||
const history = useHistory()
|
||||
const history = useNavigate()
|
||||
// console.log(token);
|
||||
useEffect(async () => {
|
||||
let res = await axios.get('/owner', {
|
||||
@ -45,35 +51,68 @@ const Profile = () => {
|
||||
</CCol>
|
||||
<CCol>
|
||||
<CButton color='dark'
|
||||
className="float-right" onClick={() => history.push('/edit')}>Edit Profile</CButton>
|
||||
className="float-right" onClick={() => history('/edit')}>Edit Profile</CButton>
|
||||
</CCol>
|
||||
</CRow>
|
||||
<CTable color="white" striped>
|
||||
<CTableHead>
|
||||
<CTableRow>
|
||||
<CTableHeaderCell scope="col">Cafe Name</CTableHeaderCell>
|
||||
<CTableDataCell scope="col">{user.cafeName}</CTableDataCell>
|
||||
</CTableRow>
|
||||
</CTableHead>
|
||||
<CTableBody>
|
||||
<CTableRow>
|
||||
<CTableHeaderCell scope="col">Email</CTableHeaderCell>
|
||||
<CTableDataCell scope="col">{user.email}</CTableDataCell>
|
||||
</CTableRow>
|
||||
<CCard className="p-4">
|
||||
<CCardBody>
|
||||
{/* <h1 >Edit Profile</h1> */}
|
||||
<CForm className="row g-3">
|
||||
<CCol xs={12}>
|
||||
<CFormLabel htmlFor="inputAddress">Cafe Name</CFormLabel>
|
||||
<CFormInput id="inputAddress" placeholder="" name='cafeName' value={"jsw"} />
|
||||
</CCol>
|
||||
|
||||
<CTableRow>
|
||||
<CTableHeaderCell scope="row">Address</CTableHeaderCell>
|
||||
<CTableDataCell>{user.location},{user.city},{user.country}</CTableDataCell>
|
||||
</CTableRow>
|
||||
<CCol md={6}>
|
||||
<CFormLabel htmlFor="inputEmail4">Email</CFormLabel>
|
||||
<CFormInput type="email" id="inputEmail4" name='email' value={"habhs"} />
|
||||
</CCol>
|
||||
{/* <CCol md={6}>
|
||||
<CFormLabel htmlFor="inputPassword4">Password</CFormLabel>
|
||||
<CFormInput type="password" id="inputPassword4" name='password' value={ownerDetails.password} onChange={handleChange} />
|
||||
</CCol> */}
|
||||
|
||||
<CTableRow>
|
||||
<CTableHeaderCell scope="row">Item_Name</CTableHeaderCell>
|
||||
<CTableDataCell><img src={user.qr_code} alt="" /></CTableDataCell>
|
||||
</CTableRow>
|
||||
|
||||
</CTableBody>
|
||||
</CTable>
|
||||
</div>
|
||||
<CCol md={12}>
|
||||
<CFormLabel htmlFor="inputCity">Location</CFormLabel>
|
||||
<CFormInput id="inputCity" name='location' value={"ajnsj"} />
|
||||
</CCol>
|
||||
<CCol md={12}>
|
||||
<CFormLabel htmlFor="inputCity">image</CFormLabel>
|
||||
<CFormInput
|
||||
type="file"
|
||||
placeholder="image"
|
||||
accept="image/*"
|
||||
required
|
||||
// onChange={handleImage}
|
||||
|
||||
|
||||
/>
|
||||
</CCol>
|
||||
{/* <CCol md={6}>
|
||||
<CFormLabel htmlFor="inputState">Country</CFormLabel>
|
||||
<CFormSelect id="inputState" name='country' >
|
||||
<option>Select a country</option>
|
||||
{countries.map(item => <option value={item.name}>{item.name}</option>)}
|
||||
|
||||
</CFormSelect>
|
||||
</CCol> */}
|
||||
{/* <CCol md={6}>
|
||||
<CFormLabel htmlFor="inputState">City</CFormLabel>
|
||||
<CFormSelect id="inputState" name='city' >
|
||||
<option>Select a city</option>
|
||||
{cities.map(item => <option value={item.name}>{item.name}</option>)}
|
||||
|
||||
</CFormSelect>
|
||||
</CCol> */}
|
||||
|
||||
{/* <CCol xs={12}>
|
||||
<CButton onClick={handleSubmit} color='dark'>Submit</CButton>
|
||||
</CCol> */}
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
||||
|
407
src/views/Temples/AddTemple.js
Normal file
407
src/views/Temples/AddTemple.js
Normal file
@ -0,0 +1,407 @@
|
||||
|
||||
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
// import { WebsiteURL } from '../WebsiteURL'
|
||||
|
||||
const AddTemple = () => {
|
||||
const [WebsiteURL, setWebsiteURL] = useState('https://reinventuniforms.in/')
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [data, setData] = useState({
|
||||
image: '',
|
||||
imageURL: '',
|
||||
name: '',
|
||||
address_line_1: '',
|
||||
address_line_2: '',
|
||||
city: '',
|
||||
state_name: '',
|
||||
short_url: '',
|
||||
// pan: '',
|
||||
// business_name: '',
|
||||
// gstin: '',
|
||||
// option: '',
|
||||
})
|
||||
|
||||
const [cities, setCities] = useState([])
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
name: 100,
|
||||
nameHas: 100,
|
||||
})
|
||||
|
||||
const getRequired = () => {
|
||||
axios
|
||||
.get(`/api/city`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setCities([...res.data.data])
|
||||
})
|
||||
.catch((err) => { })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getRequired()
|
||||
}, [])
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.id === 'name') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
setData((prev) => ({ ...prev, short_url: e.target.value.toLowerCase().replace(/\s+/g, '-') }))
|
||||
}
|
||||
if (e.target.id === 'city') {
|
||||
const city = cities.filter((m) => e.target.value === m?._id)
|
||||
setData((prev) => ({ ...prev, state_name: city[0]?.state?.state_name || '' }))
|
||||
}
|
||||
if (e.target.id === 'image') {
|
||||
if (
|
||||
e.target.files[0]?.type === 'image/jpeg' ||
|
||||
e.target.files[0]?.type === 'image/png' ||
|
||||
e.target.files[0]?.type === 'image/jpg'
|
||||
) {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: URL.createObjectURL(e.target.files[0]),
|
||||
image: e.target.files[0],
|
||||
}))
|
||||
return
|
||||
} else {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Upload jpg, jpeg, png only.',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: '',
|
||||
image: '',
|
||||
}))
|
||||
e.target.value = null
|
||||
return
|
||||
}
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (
|
||||
data.name.trim() === '' ||
|
||||
// data.pan.trim() === '' ||
|
||||
// data.business_name.trim() === '' ||
|
||||
// data.gstin.trim() === '' ||
|
||||
// data.option.trim() === '' ||
|
||||
data.address_line_1.trim() === '' ||
|
||||
data.address_line_2.trim() === '' ||
|
||||
data.city === '' ||
|
||||
data.short_url === '' ||
|
||||
data.state_name === '' ||
|
||||
data.imageURL.trim() === ''
|
||||
) {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
const formData = new FormData()
|
||||
formData.set('name', data.name)
|
||||
// formData.set('pan', data.pan)
|
||||
// formData.set('business_name', data.business_name)
|
||||
// formData.set('gstin', data.gstin)
|
||||
// formData.set('option', data.option)
|
||||
formData.set('address_line_1', data.address_line_1)
|
||||
formData.set('address_line_2', data.address_line_2)
|
||||
formData.set('city', data.city)
|
||||
formData.set('state_name', data.state_name)
|
||||
formData.set('url', WebsiteURL + data.short_url + '/login')
|
||||
formData.set('short_url', data.short_url)
|
||||
formData.append('image', data.image)
|
||||
axios
|
||||
.post(`/api/temple`, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Added',
|
||||
text: 'Temple added successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/temples', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
const message = err.response?.data?.message || 'Something went wrong!'
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: message,
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Add Temple
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Save'}
|
||||
</Button>
|
||||
<Link to="/temples">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-6 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Temple Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={data.name}
|
||||
maxLength={limiter.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Remaining characters : {limiter.nameHas}</p>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
PAN*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="pan"
|
||||
value={data.pan}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address Line 1*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address_line_1"
|
||||
value={data.address_line_1}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address Line 2*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address_line_2"
|
||||
value={data.address_line_2}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Business Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="business_name"
|
||||
value={data.business_name}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div> */}
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
GSTIN*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="gstin"
|
||||
value={data.gstin}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="pageToLink" className="form-label">
|
||||
City*
|
||||
</label>
|
||||
<select
|
||||
onChange={(e) => handleChange(e)}
|
||||
value={data.city}
|
||||
className="form-control"
|
||||
id="city"
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{cities[0] ? (
|
||||
cities.map((c, i) => (
|
||||
<option key={i} value={c._id}>
|
||||
{c.city_name + ', ' + c.state?.state_name}
|
||||
</option>
|
||||
))
|
||||
) : (
|
||||
<option value="" disabled>
|
||||
Please add a City
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
State*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_name"
|
||||
value={data.state_name}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
URL*
|
||||
</label>
|
||||
<div className="input-group mb-3">
|
||||
<span className="input-group-text" id="basic-addon3">
|
||||
{WebsiteURL}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="short_url"
|
||||
aria-describedby="basic-addon3"
|
||||
value={data.short_url}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="option" className="form-label">
|
||||
Option*
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
id="option"
|
||||
value={data.option}
|
||||
onChange={(e) => handleChange(e)}
|
||||
>
|
||||
<option value="">None</option>
|
||||
<option value="group">Group</option>
|
||||
<option value="bundle">Bundle</option>
|
||||
</select>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="image" className="form-label">
|
||||
Temple Banner*
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
className="form-control"
|
||||
id="image"
|
||||
accept="image/*"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Upload jpg, jpeg and png only*</p>
|
||||
</div>
|
||||
<div className="mb-3" style={{ height: '200px', maxWdth: '100%' }}>
|
||||
<img
|
||||
src={data.imageURL}
|
||||
alt="Uploaded Image will be shown here"
|
||||
style={{ maxHeight: '200px', maxWidth: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddTemple
|
423
src/views/Temples/EditTemple.js
Normal file
423
src/views/Temples/EditTemple.js
Normal file
@ -0,0 +1,423 @@
|
||||
|
||||
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
const EditTemple = () => {
|
||||
|
||||
|
||||
const [WebsiteURL, setWebsiteURL] = useState('https://reinventuniforms.in/')
|
||||
const id = useParams()?.id
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [data, setData] = useState({
|
||||
image: '',
|
||||
imageURL: '',
|
||||
name: '',
|
||||
address_line_1: '',
|
||||
address_line_2: '',
|
||||
city: '',
|
||||
state_name: '',
|
||||
short_url: '',
|
||||
pan: '',
|
||||
business_name: '',
|
||||
gstin: '',
|
||||
option: '',
|
||||
})
|
||||
const [cities, setCities] = useState([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
name: 100,
|
||||
nameHas: 100,
|
||||
})
|
||||
|
||||
const getRequired = async () => {
|
||||
await axios
|
||||
.get(`/api/city`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setCities([...res.data.data])
|
||||
})
|
||||
.catch((err) => { })
|
||||
axios
|
||||
.get(`/api/Temple/withoutpopulate/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
...res.data?.data,
|
||||
city: res.data?.data?.city,
|
||||
imageURL: res.data?.data?.banner?.url,
|
||||
}))
|
||||
setLimiter((prev) => ({ ...prev, nameHas: prev.name - res.data?.data?.name?.length || 0 }))
|
||||
})
|
||||
.catch((err) => { })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getRequired()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const setStateName = () => {
|
||||
const city = cities.filter((m) => data.city === m?._id)
|
||||
setData((prev) => ({ ...prev, state_name: city[0]?.state?.state_name || '' }))
|
||||
}
|
||||
setStateName()
|
||||
}, [data.city])
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.id === 'name') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
// setData((prev) => ({ ...prev, short_url: e.target.value.toLowerCase().replace(/\s+/g, '-') }))
|
||||
}
|
||||
if (e.target.id === 'image') {
|
||||
if (
|
||||
e.target.files[0]?.type === 'image/jpeg' ||
|
||||
e.target.files[0]?.type === 'image/png' ||
|
||||
e.target.files[0]?.type === 'image/jpg'
|
||||
) {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: URL.createObjectURL(e.target.files[0]),
|
||||
image: e.target.files[0],
|
||||
}))
|
||||
return
|
||||
} else {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Upload jpg, jpeg, png only.',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
imageURL: '',
|
||||
image: '',
|
||||
}))
|
||||
e.target.value = null
|
||||
return
|
||||
}
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (
|
||||
data.name.trim() === '' ||
|
||||
data.address_line_1.trim() === '' ||
|
||||
data.address_line_2.trim() === '' ||
|
||||
data.city === '' ||
|
||||
data.short_url === '' ||
|
||||
data.state_name === ''
|
||||
) {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
const formData = new FormData()
|
||||
formData.set('name', data.name)
|
||||
// formData.set('pan', data.pan)
|
||||
// formData.set('business_name', data.business_name)
|
||||
// formData.set('gstin', data.gstin)
|
||||
// formData.set('option', data.option)
|
||||
formData.set('address_line_1', data.address_line_1)
|
||||
formData.set('address_line_2', data.address_line_2)
|
||||
formData.set('city', data.city)
|
||||
formData.set('state_name', data.state_name)
|
||||
formData.set('url', WebsiteURL + data.short_url + '/login')
|
||||
formData.set('short_url', data.short_url)
|
||||
formData.append('image', data.image)
|
||||
axios
|
||||
.patch(`/api/Temple/${id}`, formData, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Updated',
|
||||
text: 'Temple updated successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/temples', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
const message = err.response?.data?.message || 'Something went wrong!'
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: message,
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Edit Temple
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Update'}
|
||||
</Button>
|
||||
<Link to="/temples">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-6 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Temple Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="name"
|
||||
value={data.name}
|
||||
maxLength={limiter.name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Remaining characters : {limiter.nameHas}</p>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
PAN*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="pan"
|
||||
value={data.pan}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address Line 1*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address_line_1"
|
||||
value={data.address_line_1}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Address Line 2*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="address_line_2"
|
||||
value={data.address_line_2}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
Business Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="business_name"
|
||||
value={data.business_name}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
GSTIN*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="gstin"
|
||||
value={data.gstin}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="pageToLink" className="form-label">
|
||||
City*
|
||||
</label>
|
||||
<select
|
||||
onChange={(e) => handleChange(e)}
|
||||
value={data.city}
|
||||
className="form-control"
|
||||
id="city"
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{cities[0] ? (
|
||||
cities.map((c, i) => (
|
||||
<option key={i} value={c._id}>
|
||||
{c.city_name + ', ' + c.state?.state_name}
|
||||
</option>
|
||||
))
|
||||
) : (
|
||||
<option value="" disabled>
|
||||
Please add a City
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
State*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_name"
|
||||
value={data.state_name}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-6 my-1">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="title" className="form-label">
|
||||
URL*
|
||||
</label>
|
||||
<div className="input-group mb-3">
|
||||
<span className="input-group-text" id="basic-addon3">
|
||||
{WebsiteURL}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="short_url"
|
||||
aria-describedby="basic-addon3"
|
||||
value={data.short_url}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="option" className="form-label">
|
||||
Option*
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
id="option"
|
||||
value={data.option}
|
||||
onChange={(e) => handleChange(e)}
|
||||
>
|
||||
<option value="">None</option>
|
||||
<option value="group">Group</option>
|
||||
<option value="bundle">Bundle</option>
|
||||
</select>
|
||||
</div> */}
|
||||
<div className="mb-3">
|
||||
<label htmlFor="image" className="form-label">
|
||||
Temple Banner*
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
className="form-control"
|
||||
id="image"
|
||||
accept="image/*"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">Upload jpg, jpeg and png only*</p>
|
||||
</div>
|
||||
<div className="mb-3" style={{ height: '200px', maxWdth: '100%' }}>
|
||||
<img
|
||||
src={data.imageURL}
|
||||
alt="Uploaded Image will be shown here"
|
||||
style={{ maxHeight: '200px', maxWidth: '100%' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditTemple
|
29
src/views/Temples/OverLayButton.js
Normal file
29
src/views/Temples/OverLayButton.js
Normal file
@ -0,0 +1,29 @@
|
||||
import React, { useState, useRef } from 'react'
|
||||
import Button from 'react-bootstrap/Button'
|
||||
import Overlay from 'react-bootstrap/Overlay'
|
||||
import Tooltip from 'react-bootstrap/Tooltip'
|
||||
|
||||
function OverLayButton(props) {
|
||||
const { url } = props?.data || ''
|
||||
const [show, setShow] = useState(false)
|
||||
const target = useRef(null)
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Button ref={target} onClick={() => setShow(!show)} size="sm" variant="outline-info">
|
||||
URL
|
||||
</Button>
|
||||
<Overlay target={target.current} show={show} placement="top">
|
||||
{(props) => (
|
||||
<Tooltip id="overlay-example" {...props}>
|
||||
<a href={url} target="_blank" className="text-white">
|
||||
{url}
|
||||
</a>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Overlay>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default OverLayButton
|
351
src/views/Temples/Temples.js
Normal file
351
src/views/Temples/Temples.js
Normal file
@ -0,0 +1,351 @@
|
||||
|
||||
import React, { useEffect } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import swal from 'sweetalert'
|
||||
import OverLayButton from './OverLayButton.js'
|
||||
import { isAutheticated } from 'src/auth.js'
|
||||
|
||||
const Temples = () => {
|
||||
const token = isAutheticated()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [success, setSuccess] = useState(true)
|
||||
const [TemplesData, setTemplesData] = useState([])
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1)
|
||||
const [itemPerPage, setItemPerPage] = useState(10)
|
||||
const [showData, setShowData] = useState(TemplesData)
|
||||
|
||||
const handleShowEntries = (e) => {
|
||||
setCurrentPage(1)
|
||||
setItemPerPage(e.target.value)
|
||||
}
|
||||
|
||||
const getCategories = () => {
|
||||
axios
|
||||
.get(`/api/temple`, {
|
||||
headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
setTemplesData(res.data.data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCategories()
|
||||
}, [success])
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = () => {
|
||||
const indexOfLastPost = currentPage * itemPerPage
|
||||
const indexOfFirstPost = indexOfLastPost - itemPerPage
|
||||
setShowData(TemplesData.slice(indexOfFirstPost, indexOfLastPost))
|
||||
}
|
||||
loadData()
|
||||
}, [currentPage, itemPerPage, TemplesData])
|
||||
|
||||
const handleDelete = (id) => {
|
||||
swal({
|
||||
title: 'Are you sure?',
|
||||
icon: 'error',
|
||||
buttons: { Yes: { text: 'Yes', value: true }, Cancel: { text: 'Cancel', value: 'cancel' } },
|
||||
}).then((value) => {
|
||||
if (value === true) {
|
||||
axios
|
||||
.delete(`/api/temple/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setSuccess((prev) => !prev)
|
||||
})
|
||||
.catch((err) => {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Temples
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Link to="/temple/add">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Add Temple
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: '10%' }}
|
||||
name=""
|
||||
onChange={(e) => handleShowEntries(e)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: '1px solid' }}
|
||||
>
|
||||
<thead className="thead-info" style={{ background: 'rgb(140, 213, 213)' }}>
|
||||
<tr>
|
||||
<th className="text-start">Temple Name</th>
|
||||
<th className="text-start">Logo</th>
|
||||
<th className="text-start">City </th>
|
||||
<th className="text-start">Created On</th>
|
||||
<th className="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && showData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="6">
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="6">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
showData.map((temple, i) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td className="text-start">{temple.name}</td>
|
||||
<td className="text-start">
|
||||
<img src={temple.banner.url} alt="Test Image" height="50" />
|
||||
</td>
|
||||
<td className="text-start">{temple?.city?.city_name}</td>
|
||||
<td className="text-start">
|
||||
{new Date(temple.createdAt).toLocaleString('en-IN', {
|
||||
month: '2-digit',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
// hour: 'numeric',
|
||||
// minute: 'numeric',
|
||||
// hour12: true,
|
||||
})}
|
||||
</td>
|
||||
<td className=" text-center">
|
||||
<OverLayButton data={{ url: temple?.url }} />
|
||||
|
||||
<Link to={`/temple/products/${temple._id}`}>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
ms-2
|
||||
"
|
||||
>
|
||||
Products
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
<Link to={`/temple/edit/${temple._id}`}>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-success btn-sm
|
||||
waves-effect waves-light
|
||||
ms-2
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-danger btn-sm
|
||||
waves-effect waves-light
|
||||
ms-2
|
||||
|
||||
"
|
||||
onClick={() => {
|
||||
handleDelete(temple._id)
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{' '}
|
||||
{Math.min(currentPage * itemPerPage, TemplesData.length)} of{' '}
|
||||
{TemplesData.length} entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div className="d-flex">
|
||||
<ul className="pagination ms-auto">
|
||||
<li
|
||||
className={
|
||||
currentPage === 1
|
||||
? 'paginate_button page-item previous disabled'
|
||||
: 'paginate_button page-item previous'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
Previous
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(currentPage - 1 < 1) && (
|
||||
<li className="paginate_button page-item">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
{currentPage - 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li className="paginate_button page-item active">
|
||||
<span className="page-link" style={{ cursor: 'pointer' }}>
|
||||
{currentPage}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
TemplesData.length - 1
|
||||
) && (
|
||||
<li className="paginate_button page-item ">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setCurrentPage((prev) => prev + 1)
|
||||
}}
|
||||
>
|
||||
{currentPage + 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li
|
||||
className={
|
||||
!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
TemplesData.length - 1
|
||||
)
|
||||
? 'paginate_button page-item next'
|
||||
: 'paginate_button page-item next disabled'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev + 1)}
|
||||
>
|
||||
Next
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Temples
|
25
src/views/Users/Pagination.js
Normal file
25
src/views/Users/Pagination.js
Normal file
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import { Link } from "react-router-dom";
|
||||
const Pagination = ({ userPerPage, totalUsers, paginate }) => {
|
||||
const pageNumbers = [];
|
||||
|
||||
for (let i = 1; i <= Math.ceil(totalUsers / userPerPage); i++) {
|
||||
pageNumbers.push(i);
|
||||
}
|
||||
|
||||
return (
|
||||
<nav>
|
||||
<ul className='ml-3 pagination '>
|
||||
{pageNumbers.map(number => (
|
||||
<li key={number} className='page-item'>
|
||||
<Link onClick={() => paginate(number)} to="/users" className='page-link'>
|
||||
{number}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default Pagination;
|
131
src/views/Users/ViewUsers.js
Normal file
131
src/views/Users/ViewUsers.js
Normal file
@ -0,0 +1,131 @@
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import swal from 'sweetalert';
|
||||
// import { API } from "../../data";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { isAutheticated } from "../../auth";
|
||||
|
||||
function ViewUsers() {
|
||||
const [user, setUser] = useState([])
|
||||
const { id } = useParams();
|
||||
// console.log(id)
|
||||
const token = isAutheticated();
|
||||
|
||||
const getUserDetails = useCallback(async () => {
|
||||
|
||||
|
||||
let resp = await axios.get(
|
||||
`/api/v1/admin/user/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
setUser(resp.data.user)
|
||||
|
||||
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
getUserDetails();
|
||||
}, [getUserDetails]);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//change time formate
|
||||
function formatAMPM(date) {
|
||||
var hours = new Date(date).getHours();
|
||||
var minutes = new Date(date).getMinutes();
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">CMP-User Details</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
|
||||
<tr>
|
||||
<th>User_Id</th>
|
||||
|
||||
<td>{user?._id}</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr><th>Name</th>
|
||||
<td>{user?.name}</td></tr>
|
||||
|
||||
<tr><th>email</th>
|
||||
<td>{user?.email}</td></tr>
|
||||
|
||||
<tr><th>Image</th>
|
||||
<td>
|
||||
<img src={`${user.avatar?.url}`} width="50" alt="" />
|
||||
</td></tr>
|
||||
|
||||
{/* <th>Description</th> */}
|
||||
<tr><th>Phone No.</th>
|
||||
<td>{user?.phone}</td></tr>
|
||||
<tr><th>Role</th>
|
||||
<td>{user?.role}</td></tr>
|
||||
<tr><th>Register At</th>
|
||||
|
||||
<td>
|
||||
{new Date(`${user?.createdAt}`).toDateString()}<span> , {`${formatAMPM(user?.createdAt)}`}</span>
|
||||
</td></tr>
|
||||
<tr><th>Profile Updated At</th>
|
||||
<td>
|
||||
{new Date(`${user?.updatedAt}`).toDateString()}<span> , {`${formatAMPM(user?.updatedAt)}`}</span>
|
||||
</td></tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ViewUsers;
|
||||
|
153
src/views/Users/users.js
Normal file
153
src/views/Users/users.js
Normal file
@ -0,0 +1,153 @@
|
||||
|
||||
import axios from "axios";
|
||||
import React, { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import Pagination from "./Pagination";
|
||||
import { Link } from "react-router-dom";
|
||||
import swal from 'sweetalert';
|
||||
// import { API } from "../../data";
|
||||
import { isAutheticated } from "../../auth";
|
||||
|
||||
function users() {
|
||||
const [users, setUsers] = useState([])
|
||||
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [userPerPage] = useState(10);
|
||||
const token = isAutheticated();
|
||||
|
||||
const getAllUsers = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/v1/admin/users`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
// console.log(res.data)
|
||||
setUsers(res.data.users)
|
||||
|
||||
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
getAllUsers();
|
||||
}, [getAllUsers]);
|
||||
|
||||
|
||||
// console.log(cmsRes)
|
||||
|
||||
// Get current posts
|
||||
//pagination
|
||||
const indexOfLastUser = currentPage * userPerPage;
|
||||
const indexOfFirstUser = indexOfLastUser - userPerPage;
|
||||
const currentUser = users.slice(indexOfFirstUser, indexOfLastUser);
|
||||
|
||||
// Change page
|
||||
const paginate = pageNumber => setCurrentPage(pageNumber);
|
||||
|
||||
//change time formate
|
||||
function formatAMPM(date) {
|
||||
var hours = new Date(date).getHours();
|
||||
var minutes = new Date(date).getMinutes();
|
||||
var ampm = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12;
|
||||
hours = hours ? hours : 12; // the hour '0' should be '12'
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
var strTime = hours + ':' + minutes + ' ' + ampm;
|
||||
return strTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className=" main-content">
|
||||
<div className=" my-3 page-content">
|
||||
<div className="container-fluid">
|
||||
{/* <!-- start page title --> */}
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||
<h4 className="mb-3">CMP - All Users</h4>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- end page title --> */}
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
|
||||
</div>
|
||||
<div className="table-responsive table-shoot">
|
||||
<table className="table table-centered table-nowrap mb-0">
|
||||
<thead className="thead-light">
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
<th>email</th>
|
||||
<th>Profile Image</th>
|
||||
<th>Phone No.</th>
|
||||
<th>Register At</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{currentUser && currentUser.map((item, index) =>
|
||||
<tr>
|
||||
|
||||
<td>{item?.name}</td>
|
||||
<td>{item?.email}</td>
|
||||
<td>
|
||||
<img src={`${item.avatar?.url}`} width="50" alt="" />
|
||||
</td>
|
||||
<td>{item?.phone}</td>
|
||||
|
||||
|
||||
<td>
|
||||
|
||||
{new Date(`${item?.createdAt}`).toDateString()}<span> , {`${formatAMPM(item?.createdAt)}`}</span>
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
<td>
|
||||
<Link to={`/users/view/${item._id}`}>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="mt-1 btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</Link>
|
||||
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
</div>
|
||||
<Pagination userPerPage={userPerPage}
|
||||
totalUsers={users.length}
|
||||
paginate={paginate} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default users;
|
293
src/views/configuration/Address.js
Normal file
293
src/views/configuration/Address.js
Normal file
@ -0,0 +1,293 @@
|
||||
import axios from 'axios'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import ClipLoader from 'react-spinners/ClipLoader'
|
||||
import { Link } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
|
||||
function Address() {
|
||||
const token = isAutheticated()
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [company, setCompany] = useState('')
|
||||
const [address, setAddress] = useState('')
|
||||
const [city, setCity] = useState('')
|
||||
const [state, setState] = useState('')
|
||||
const [country, setCountry] = useState('')
|
||||
const [pincode, setPincode] = useState('')
|
||||
const [website, setWebsite] = useState('')
|
||||
const [contact, setContact] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [gstin, setGSTIN] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
async function getConfiguration() {
|
||||
const configDetails = await axios.get(`/api/config`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
configDetails.data.result.map((item) => {
|
||||
item.address.map((el) => {
|
||||
setCompany(el.company)
|
||||
setAddress(el.address)
|
||||
setCity(el.city)
|
||||
setState(el.state)
|
||||
setCountry(el.country)
|
||||
setPincode(el.pincode)
|
||||
setWebsite(el.website)
|
||||
setContact(el.contact)
|
||||
setEmail(el.email)
|
||||
setGSTIN(el?.gstin)
|
||||
})
|
||||
})
|
||||
}
|
||||
getConfiguration()
|
||||
}, [])
|
||||
async function handelChange(e) {
|
||||
if (e.target.name.toLowerCase() === 'address') {
|
||||
setAddress(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'company name') {
|
||||
setCompany(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'city') {
|
||||
setCity(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'state') {
|
||||
setState(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'country') {
|
||||
setCountry(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'pincode') {
|
||||
setPincode(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'website') {
|
||||
setWebsite(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'contact number') {
|
||||
setContact(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'email') {
|
||||
setEmail(e.target.value)
|
||||
} else if (e.target.name.toLowerCase() === 'gstin') {
|
||||
setGSTIN(e.target.value)
|
||||
}
|
||||
}
|
||||
async function handelSubmit() {
|
||||
if (!/^[0-9A-Za-z]{15}$/.test(gstin)) return swal('Warning!', 'Enter valid GSTIN')
|
||||
setLoading(true)
|
||||
let data = {
|
||||
company,
|
||||
address,
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
pincode,
|
||||
website,
|
||||
contact,
|
||||
email,
|
||||
gstin,
|
||||
}
|
||||
let res = await axios.post(`/api/config/address`, data, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (res) {
|
||||
setLoading(false)
|
||||
console.log(res)
|
||||
swal('Success!', res.data.message, res.data.status)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12 col-lg-6 col-xl-6">
|
||||
<h1 className="text-left head-small">Address</h1>
|
||||
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Company Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="company name"
|
||||
value={company}
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Address
|
||||
</label>
|
||||
<input
|
||||
value={address}
|
||||
type="text"
|
||||
name="address"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
City
|
||||
</label>
|
||||
<input
|
||||
value={city}
|
||||
type="text"
|
||||
name="city"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
State
|
||||
</label>
|
||||
<input
|
||||
value={state}
|
||||
type="text"
|
||||
name="state"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Country
|
||||
</label>
|
||||
<input
|
||||
value={country}
|
||||
type="text"
|
||||
name="country"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Pin Code
|
||||
</label>
|
||||
<input
|
||||
value={pincode}
|
||||
type="text"
|
||||
name="pincode"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
GSTIN
|
||||
</label>
|
||||
<input
|
||||
value={gstin}
|
||||
type="text"
|
||||
name="gstin"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Website
|
||||
</label>
|
||||
<input
|
||||
value={website}
|
||||
type="text"
|
||||
name="website"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Contact Number
|
||||
</label>
|
||||
<input
|
||||
value={contact}
|
||||
type="text"
|
||||
name="contact number"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
value={email}
|
||||
type="text"
|
||||
name="email"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row mt-2">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group text-left">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handelSubmit}
|
||||
className="btn btn-success btn-login waves-effect waves-light mr-3 pt-2 pb-2 pr-4 pl-4"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
{/* <!-- End Page-content --> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Address
|
222
src/views/configuration/Logo.js
Normal file
222
src/views/configuration/Logo.js
Normal file
@ -0,0 +1,222 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import swal from 'sweetalert'
|
||||
import ClipLoader from 'react-spinners/ClipLoader'
|
||||
import { Link } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
function Logo() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [Headerlogo, setHeaderlogo] = useState('')
|
||||
const [Footerlogo, setFooterlogo] = useState('')
|
||||
const [Adminlogo, setAdminlogo] = useState('')
|
||||
const [display, setDisplay] = useState(true)
|
||||
const token = isAutheticated()
|
||||
|
||||
// urlcreated images
|
||||
|
||||
const [HeaderlogoUrl, setHeaderlogoUrl] = useState('')
|
||||
const [FooterlogoUrl, setFooterlogoUrl] = useState('')
|
||||
const [AdminlogoUrl, setAdminlogoUrl] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
async function getConfiguration() {
|
||||
const configDetails = await axios.get(`/api/config`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
configDetails.data.result.map((item) => {
|
||||
setHeaderlogo(item?.logo[0]?.Headerlogo)
|
||||
setFooterlogo(item?.logo[0]?.Footerlogo)
|
||||
setAdminlogo(item?.logo[0]?.Adminlogo)
|
||||
})
|
||||
}
|
||||
getConfiguration()
|
||||
}, [])
|
||||
|
||||
// async function handelChange(e) {
|
||||
// setDisplay(false);
|
||||
// console.log(e.target.name === "Logo htmlFor Website Header(148 x 48 px)");
|
||||
// if (e.target.name === "Logo htmlFor Website Header(148 x 48 px)") {
|
||||
// console.log(e.target.files[0]);
|
||||
// setHeaderlogo(e.target.files[0]);
|
||||
// } else if (e.target.name === "Logo htmlFor Website Footer(148 x 48 px)") {
|
||||
// setFooterlogo(e.target.files[0]);
|
||||
// } else if (e.target.name === "Logo htmlFor Admin Header(148 x 48 px)") {
|
||||
// setAdminlogo(e.target.files[0]);
|
||||
// }
|
||||
// }
|
||||
|
||||
async function handelSubmit() {
|
||||
setLoading(true)
|
||||
|
||||
const formdata = new FormData()
|
||||
formdata.append('Headerlogo', Headerlogo)
|
||||
formdata.append('Footerlogo', Footerlogo)
|
||||
formdata.append('Adminlogo', Adminlogo)
|
||||
|
||||
await axios.post(`/api/config/logo`, formdata, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'Content-Type': 'multipart/formdata',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
}).then((res) => {
|
||||
setLoading(false)
|
||||
swal('Success!', res.data.message, res.data.status)
|
||||
}
|
||||
).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12 col-lg-6 col-xl-6">
|
||||
<h1 className="text-left head-small">Logo</h1>
|
||||
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
{/* Logo htmlFor Website Header(148 x 48 px) */}
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
type="file"
|
||||
name="Logo htmlFor Website Header(148 x 48 px)"
|
||||
onChange={(e) => {
|
||||
setHeaderlogo(e.target.files[0])
|
||||
if (e.target.files && e.target.files[0]) {
|
||||
setHeaderlogoUrl({
|
||||
image: URL.createObjectURL(e.target.files[0]),
|
||||
})
|
||||
console.log(setHeaderlogoUrl)
|
||||
}
|
||||
}}
|
||||
className="form-control input-field mb-3 col-md-6 d-inline-block"
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
{display ? (
|
||||
<img className='ms-1'
|
||||
style={{ width: '100px' }}
|
||||
src={HeaderlogoUrl.image ? HeaderlogoUrl.image : Headerlogo}
|
||||
alt="header logo"
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-3"
|
||||
>
|
||||
{/* Logo htmlFor Website Footer(148 x 48 px) */}
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
name="Logo htmlFor Website Footer(148 x 48 px)"
|
||||
onChange={(e) => {
|
||||
setFooterlogo(e.target.files[0])
|
||||
|
||||
if (e.target.files && e.target.files[0]) {
|
||||
setFooterlogoUrl({
|
||||
image: URL.createObjectURL(e.target.files[0]),
|
||||
})
|
||||
}
|
||||
}}
|
||||
className="form-control input-field mt-1 col-md-6 d-inline-block"
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
{display ? (
|
||||
<img
|
||||
style={{ width: '100px' }}
|
||||
src={FooterlogoUrl.image ? FooterlogoUrl.image : Footerlogo}
|
||||
alt="Footer logo"
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<label
|
||||
htmlFor="basicpill-phoneno-input"
|
||||
className="label-100 mt-2 row ms-1"
|
||||
>
|
||||
{/* Logo htmlFor Admin Header(148 x 48 px) */}
|
||||
</label>
|
||||
<input
|
||||
type="file"
|
||||
name="Logo htmlFor Admin Header(148 x 48 px)"
|
||||
onChange={(e) => {
|
||||
setAdminlogo(e.target.files[0])
|
||||
|
||||
if (e.target.files && e.target.files[0]) {
|
||||
setAdminlogoUrl({
|
||||
image: URL.createObjectURL(e.target.files[0]),
|
||||
})
|
||||
}
|
||||
}}
|
||||
className="form-control input-field col-md-6 d-inline-block"
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
{display ? (
|
||||
<img
|
||||
style={{ width: '100px' }}
|
||||
src={AdminlogoUrl.image ? AdminlogoUrl.image : Adminlogo}
|
||||
alt="Admin logo"
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group text-left">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handelSubmit}
|
||||
className="btn btn-success btn-login waves-effect waves-light mr-3 pt-2 pb-2 pr-4 pl-4"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
{/* <!-- End Page-content --> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Logo
|
169
src/views/configuration/Socialmedia.js
Normal file
169
src/views/configuration/Socialmedia.js
Normal file
@ -0,0 +1,169 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import ClipLoader from 'react-spinners/ClipLoader'
|
||||
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
function Socialmedia() {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const token = isAutheticated()
|
||||
const [facebook, setFacebook] = useState('')
|
||||
const [instagram, setInstagram] = useState('')
|
||||
const [twitter, setTwitter] = useState('')
|
||||
const [linkedin, setLinkedin] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
async function getConfiguration() {
|
||||
const configDetails = await axios.get(`/api/config`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
configDetails.data.result.map((item) => {
|
||||
console.log(item.socialMedia)
|
||||
setFacebook(item?.socialMedia[0]?.facebook)
|
||||
setInstagram(item?.socialMedia[0]?.instagram)
|
||||
setTwitter(item?.socialMedia[0]?.twitter)
|
||||
setLinkedin(item?.socialMedia[0]?.linkedin)
|
||||
})
|
||||
}
|
||||
getConfiguration()
|
||||
}, [])
|
||||
|
||||
async function handelChange(e) {
|
||||
if (e.target.name === 'facebook') {
|
||||
setFacebook(e.target.value)
|
||||
} else if (e.target.name === 'twitter') {
|
||||
setTwitter(e.target.value)
|
||||
} else if (e.target.name === 'instagram') {
|
||||
setInstagram(e.target.value)
|
||||
} else if (e.target.name === 'linkedin') {
|
||||
setLinkedin(e.target.value)
|
||||
}
|
||||
}
|
||||
async function handelSubmit() {
|
||||
setLoading(true)
|
||||
let data = {
|
||||
facebook,
|
||||
twitter,
|
||||
instagram,
|
||||
linkedin,
|
||||
}
|
||||
let res = await axios.post(`/api/config/social`, data, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (res) {
|
||||
setLoading(false)
|
||||
console.log(res)
|
||||
swal('Success!', res.data.message, res.data.status)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
{/* <Config
|
||||
heading="Social Media"
|
||||
labels={["Facebook", "Twitter", "Instagram", "LinkedIn"]}
|
||||
postUrl="social"
|
||||
/> */}
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
<div className="col-md-12 col-lg-6 col-xl-6">
|
||||
<h1 className="text-left head-small">Social Media</h1>
|
||||
|
||||
<form>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group">
|
||||
<>
|
||||
<label for="basicpill-phoneno-input" className="label-100 mt-3">
|
||||
Facebook
|
||||
</label>
|
||||
<input
|
||||
value={facebook}
|
||||
type="text"
|
||||
name="facebook"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
<label for="basicpill-phoneno-input" className="label-100 mt-3">
|
||||
Twitter
|
||||
</label>
|
||||
<input
|
||||
value={twitter}
|
||||
type="text"
|
||||
name="twitter"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
<label for="basicpill-phoneno-input" className="label-100 mt-3">
|
||||
Instagram
|
||||
</label>
|
||||
<input
|
||||
value={instagram}
|
||||
type="text"
|
||||
name="instagram"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>{' '}
|
||||
<label for="basicpill-phoneno-input" className="label-100 mt-3">
|
||||
Linkedin
|
||||
</label>
|
||||
<input
|
||||
value={linkedin}
|
||||
type="text"
|
||||
name="linkedin"
|
||||
onChange={(e) => handelChange(e)}
|
||||
className="form-control input-field "
|
||||
id="basicpill-phoneno-input"
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row mt-1">
|
||||
<div className="col-lg-12">
|
||||
<div className="form-group text-left">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handelSubmit}
|
||||
className="btn btn-success btn-login waves-effect waves-light me-3 pt-2 pb-2 pr-4 pl-4"
|
||||
>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <!-- end table-responsive --> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* <!-- container-fluid --> */}
|
||||
</div>
|
||||
{/* <!-- End Page-content --> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Socialmedia
|
211
src/views/configuration/cities/AddCity.js
Normal file
211
src/views/configuration/cities/AddCity.js
Normal file
@ -0,0 +1,211 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useParams, useNavigate } from 'react-router-dom'
|
||||
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
|
||||
const AddCity = () => {
|
||||
const token = isAutheticated();
|
||||
const navigate = useNavigate()
|
||||
const [statesData, setStatesData] = useState([])
|
||||
const [data, setData] = useState({
|
||||
city_name: '',
|
||||
state: '',
|
||||
|
||||
})
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
city_name: 30,
|
||||
city_nameHas: 30,
|
||||
})
|
||||
|
||||
const getNewId = () => {
|
||||
axios
|
||||
.get(`/api/city/newid`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData((prev) => ({ ...prev, _id: res.data.data._id }))
|
||||
})
|
||||
.catch((err) => { })
|
||||
axios
|
||||
.get(`/api/state`, {
|
||||
headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
setStatesData(res.data.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getNewId()
|
||||
}, [])
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.type === 'text') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (data.city_name.trim() === '' || data.state.trim() === '') {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
axios
|
||||
.post(`/api/city`, data, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Added',
|
||||
text: 'City added successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/cities', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Add City
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Save'}
|
||||
</Button>
|
||||
<Link to="/cities">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-8 mx-auto">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
City Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="city_name"
|
||||
value={data.city_name}
|
||||
maxLength="50"
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.city_nameHas}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Name*
|
||||
</label>
|
||||
<select
|
||||
onChange={(e) => handleChange(e)}
|
||||
value={data.state}
|
||||
className="form-control"
|
||||
id="state"
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{statesData[0] ? (
|
||||
statesData.map((c, i) => (
|
||||
<option key={i} value={c._id}>
|
||||
{c.state_name}
|
||||
</option>
|
||||
))
|
||||
) : (
|
||||
<option value="" disabled>
|
||||
Please add a City
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddCity
|
342
src/views/configuration/cities/Cities.js
Normal file
342
src/views/configuration/cities/Cities.js
Normal file
@ -0,0 +1,342 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import axios from 'axios'
|
||||
|
||||
import swal from 'sweetalert'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
const Cities = () => {
|
||||
const token = isAutheticated();
|
||||
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [success, setSuccess] = useState(true)
|
||||
const [citiesData, setCitiesData] = useState([])
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1)
|
||||
const [itemPerPage, setItemPerPage] = useState(10)
|
||||
const [showData, setShowData] = useState(citiesData)
|
||||
|
||||
const handleShowEntries = (e) => {
|
||||
setCurrentPage(1)
|
||||
setItemPerPage(e.target.value)
|
||||
}
|
||||
|
||||
const getCategories = () => {
|
||||
axios
|
||||
.get(`/api/city`, {
|
||||
headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
setCitiesData(res.data.data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCategories()
|
||||
}, [success])
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = () => {
|
||||
const indexOfLastPost = currentPage * itemPerPage
|
||||
const indexOfFirstPost = indexOfLastPost - itemPerPage
|
||||
setShowData(citiesData.slice(indexOfFirstPost, indexOfLastPost))
|
||||
}
|
||||
loadData()
|
||||
}, [currentPage, itemPerPage, citiesData])
|
||||
|
||||
const handleDelete = (id) => {
|
||||
swal({
|
||||
title: 'Are you sure?',
|
||||
icon: 'error',
|
||||
buttons: { Yes: { text: 'Yes', value: true }, Cancel: { text: 'Cancel', value: 'cancel' } },
|
||||
}).then((value) => {
|
||||
if (value === true) {
|
||||
axios
|
||||
.delete(`/api/city/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setSuccess((prev) => !prev)
|
||||
})
|
||||
.catch((err) => {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Cities
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Link to="/cities/add">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Add City
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: '10%' }}
|
||||
name=""
|
||||
onChange={(e) => handleShowEntries(e)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: '1px solid' }}
|
||||
>
|
||||
<thead className="thead" style={{ background: 'rgb(140, 213, 213)' }}>
|
||||
<tr>
|
||||
<th className="text-start">City Name</th>
|
||||
<th className="text-start">State Name</th>
|
||||
<th className="text-start">Created On</th>
|
||||
<th className="text-start">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && showData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="6">
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="6">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
showData.map((city, i) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td className="text-start">{city.city_name}</td>
|
||||
<td className="text-start">{city.state?.state_name}</td>
|
||||
<td className="text-start">
|
||||
{new Date(city.createdAt).toLocaleString('en-IN', {
|
||||
weekday: 'short',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true,
|
||||
})}
|
||||
</td>
|
||||
|
||||
<td className="text-start">
|
||||
<Link to={`/cities/edit/${city._id}`}>
|
||||
<button
|
||||
style={{ color: 'white', margin: '0 1rem' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
ml-2
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<Link
|
||||
to={'#'}
|
||||
style={{
|
||||
margin: '1rem',
|
||||
}}
|
||||
>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-danger btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
ml-2
|
||||
|
||||
"
|
||||
onClick={() => {
|
||||
handleDelete(city._id)
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{' '}
|
||||
{Math.min(currentPage * itemPerPage, citiesData.length)} of{' '}
|
||||
{citiesData.length} entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div className="d-flex">
|
||||
<ul className="pagination ms-auto">
|
||||
<li
|
||||
className={
|
||||
currentPage === 1
|
||||
? 'paginate_button page-item previous disabled'
|
||||
: 'paginate_button page-item previous'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
Previous
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(currentPage - 1 < 1) && (
|
||||
<li className="paginate_button page-item">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
{currentPage - 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li className="paginate_button page-item active">
|
||||
<span className="page-link" style={{ cursor: 'pointer' }}>
|
||||
{currentPage}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
citiesData.length - 1
|
||||
) && (
|
||||
<li className="paginate_button page-item ">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setCurrentPage((prev) => prev + 1)
|
||||
}}
|
||||
>
|
||||
{currentPage + 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li
|
||||
className={
|
||||
!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
citiesData.length - 1
|
||||
)
|
||||
? 'paginate_button page-item next'
|
||||
: 'paginate_button page-item next disabled'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev + 1)}
|
||||
>
|
||||
Next
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Cities
|
229
src/views/configuration/cities/EditCity.js
Normal file
229
src/views/configuration/cities/EditCity.js
Normal file
@ -0,0 +1,229 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
|
||||
const EditCity = () => {
|
||||
const id = useParams()?.id
|
||||
const token = isAutheticated();
|
||||
const navigate = useNavigate()
|
||||
const [statesData, setStatesData] = useState([])
|
||||
const [data, setData] = useState({
|
||||
city_name: '',
|
||||
state: '',
|
||||
|
||||
})
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
city_name: 30,
|
||||
city_nameHas: 30,
|
||||
})
|
||||
|
||||
const getCategory = () => {
|
||||
axios
|
||||
.get(`$/api/city/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
...res.data?.data,
|
||||
}))
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
city_nameHas: prev.city_name - res.data?.data?.city_name.length,
|
||||
}))
|
||||
})
|
||||
.catch((err) => { })
|
||||
axios
|
||||
.get(`/api/state`, {
|
||||
headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
setStatesData(res.data.data)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCategory()
|
||||
}, [])
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.type === 'text') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (data.city_name.trim() === '' || data.state.trim() === '') {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
axios
|
||||
.patch(`/api/city/${id}`, data, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Updated',
|
||||
text: 'City updated successfully!',
|
||||
icon: 'success',
|
||||
button: 'Close',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/cities', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Edit City
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Update'}
|
||||
</Button>
|
||||
<Link to="/cities">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-8 mx-auto">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
City Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="city_name"
|
||||
value={data.city_name}
|
||||
maxLength={limiter.city_name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.city_nameHas}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Name*
|
||||
</label>
|
||||
<select
|
||||
onChange={(e) => handleChange(e)}
|
||||
value={data.state}
|
||||
className="form-control"
|
||||
id="state"
|
||||
>
|
||||
<option value="">---select---</option>
|
||||
{statesData[0] ? (
|
||||
statesData.map((c, i) => (
|
||||
<option key={i} value={c._id}>
|
||||
{c.state_name}
|
||||
</option>
|
||||
))
|
||||
) : (
|
||||
<option value="" disabled>
|
||||
Please add a City
|
||||
</option>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label>Unique ID</label>
|
||||
<input type="text" value={data._id} className="form-control" disabled />
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label>TimeStamp</label>
|
||||
<input
|
||||
type="text"
|
||||
value={new Date(data.createdAt)}
|
||||
className="form-control"
|
||||
disabled
|
||||
/>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditCity
|
172
src/views/configuration/states/AddState.js
Normal file
172
src/views/configuration/states/AddState.js
Normal file
@ -0,0 +1,172 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
|
||||
const AddState = () => {
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [data, setData] = useState({
|
||||
state_code: '',
|
||||
state_name: '',
|
||||
})
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
state_code: 10,
|
||||
state_name: 50,
|
||||
state_codeHas: 10,
|
||||
state_nameHas: 50,
|
||||
})
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.id === 'state_code' && /^\D+$/.test(e.target.value)) return
|
||||
if (e.target.type === 'text') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (data.state_name.trim() === '') {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
axios
|
||||
.post(`/api/state`, data, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Added',
|
||||
text: 'State added successfully!',
|
||||
icon: 'success',
|
||||
button: 'Return',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/states', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Add State
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Save'}
|
||||
</Button>
|
||||
<Link to="/states">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-8 mx-auto">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_name"
|
||||
value={data.state_name}
|
||||
maxLength={limiter.state_name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.state_nameHas}
|
||||
</p>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Code (GST)*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_code"
|
||||
value={data.state_code}
|
||||
maxLength={limiter.state_code}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.state_codeHas}
|
||||
</p>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddState
|
199
src/views/configuration/states/EditStates.js
Normal file
199
src/views/configuration/states/EditStates.js
Normal file
@ -0,0 +1,199 @@
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
import swal from 'sweetalert'
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
|
||||
const EditState = () => {
|
||||
const id = useParams()?.id
|
||||
const token = isAutheticated()
|
||||
const navigate = useNavigate()
|
||||
const [data, setData] = useState({
|
||||
state_code: '',
|
||||
state_name: '',
|
||||
})
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [limiter, setLimiter] = useState({
|
||||
state_code: 10,
|
||||
state_name: 50,
|
||||
state_codeHas: 10,
|
||||
state_nameHas: 50,
|
||||
})
|
||||
|
||||
const getCategory = () => {
|
||||
axios
|
||||
.get(`/api/state/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
...res.data?.data,
|
||||
}))
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
state_nameHas: prev.state_name - res.data?.data?.state_name.length,
|
||||
state_codeHas: prev.state_code - res.data?.data?.state_code?.toString()?.length,
|
||||
}))
|
||||
})
|
||||
.catch((err) => { })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCategory()
|
||||
}, [])
|
||||
|
||||
const handleChange = (e) => {
|
||||
if (e.target.id === 'state_code' && /^\D+$/.test(e.target.value)) return
|
||||
if (e.target.type === 'text') {
|
||||
if (e.target.value.length === limiter[e.target.id] + 1) return
|
||||
setLimiter((prev) => ({
|
||||
...prev,
|
||||
[e.target.id + 'Has']: prev[e.target.id] - e.target.value.length,
|
||||
}))
|
||||
}
|
||||
setData((prev) => ({ ...prev, [e.target.id]: e.target.value }))
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (data.state_name.trim() === '') {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Fill all mandatory fields',
|
||||
icon: 'error',
|
||||
button: 'Close',
|
||||
dangerMode: true,
|
||||
})
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
axios
|
||||
.patch(`/api/state/${id}`, data, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
swal({
|
||||
title: 'Updated',
|
||||
text: 'State updated successfully!',
|
||||
icon: 'success',
|
||||
button: 'Close',
|
||||
})
|
||||
setLoading(false)
|
||||
navigate('/states', { replace: true })
|
||||
})
|
||||
.catch((err) => {
|
||||
setLoading(false)
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
Edit State
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '1rem' }}>
|
||||
<h4 className="mb-0"></h4>
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
marginRight: '5px',
|
||||
}}
|
||||
onClick={() => handleSubmit()}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? 'Loading' : 'Update'}
|
||||
</Button>
|
||||
<Link to="/states">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Back
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-8 mx-auto">
|
||||
<div className="card h-100">
|
||||
<div className="card-body px-5">
|
||||
<div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Name*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_name"
|
||||
value={data.state_name}
|
||||
maxLength={limiter.state_name}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.state_nameHas}
|
||||
</p>
|
||||
</div>
|
||||
{/* <div className="mb-3">
|
||||
<label htmlFor="city_name" className="form-label">
|
||||
State Code (GST)*
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
id="state_code"
|
||||
value={data.state_code}
|
||||
maxLength={limiter.state_code}
|
||||
onChange={(e) => handleChange(e)}
|
||||
/>
|
||||
<p className="pt-1 pl-2 text-secondary">
|
||||
Remaining characters : {limiter.state_codeHas}
|
||||
</p>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default EditState
|
342
src/views/configuration/states/States.js
Normal file
342
src/views/configuration/states/States.js
Normal file
@ -0,0 +1,342 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import Button from '@material-ui/core/Button'
|
||||
import { useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import axios from 'axios'
|
||||
|
||||
import swal from 'sweetalert'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
|
||||
const States = () => {
|
||||
const token = isAutheticated()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [success, setSuccess] = useState(true)
|
||||
const [statesData, setStatesData] = useState([])
|
||||
|
||||
const [currentPage, setCurrentPage] = useState(1)
|
||||
const [itemPerPage, setItemPerPage] = useState(10)
|
||||
const [showData, setShowData] = useState(statesData)
|
||||
|
||||
const handleShowEntries = (e) => {
|
||||
setCurrentPage(1)
|
||||
setItemPerPage(e.target.value)
|
||||
}
|
||||
|
||||
const getCategories = () => {
|
||||
axios
|
||||
.get(`/api/state`, {
|
||||
headers: { 'Access-Control-Allow-Origin': '*', Authorization: `Bearer ${token}` },
|
||||
})
|
||||
.then((res) => {
|
||||
setStatesData(res.data.data)
|
||||
setLoading(false)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getCategories()
|
||||
}, [success])
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = () => {
|
||||
const indexOfLastPost = currentPage * itemPerPage
|
||||
const indexOfFirstPost = indexOfLastPost - itemPerPage
|
||||
setShowData(statesData.slice(indexOfFirstPost, indexOfLastPost))
|
||||
}
|
||||
loadData()
|
||||
}, [currentPage, itemPerPage, statesData])
|
||||
|
||||
const handleDelete = (id) => {
|
||||
swal({
|
||||
title: 'Are you sure?',
|
||||
icon: 'error',
|
||||
buttons: { Yes: { text: 'Yes', value: true }, Cancel: { text: 'Cancel', value: 'cancel' } },
|
||||
}).then((value) => {
|
||||
if (value === true) {
|
||||
axios
|
||||
.delete(`/api/state/${id}`, {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setSuccess((prev) => !prev)
|
||||
})
|
||||
.catch((err) => {
|
||||
swal({
|
||||
title: 'Warning',
|
||||
text: 'Something went wrong!',
|
||||
icon: 'error',
|
||||
button: 'Retry',
|
||||
dangerMode: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="main-content">
|
||||
<div className="page-content">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-12">
|
||||
<div
|
||||
className="
|
||||
page-title-box
|
||||
d-flex
|
||||
align-items-center
|
||||
justify-content-between
|
||||
"
|
||||
>
|
||||
<div style={{ fontSize: '22px' }} className="fw-bold">
|
||||
States
|
||||
</div>
|
||||
|
||||
<div className="page-title-right">
|
||||
<Link to="/states/add">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '1rem',
|
||||
textTransform: 'capitalize',
|
||||
}}
|
||||
>
|
||||
Add State
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="col-lg-12">
|
||||
<div className="card">
|
||||
<div className="card-body">
|
||||
<div className="row ml-0 mr-0 mb-10">
|
||||
<div className="col-sm-12 col-md-12">
|
||||
<div className="dataTables_length">
|
||||
<label className="w-100">
|
||||
Show
|
||||
<select
|
||||
style={{ width: '10%' }}
|
||||
name=""
|
||||
onChange={(e) => handleShowEntries(e)}
|
||||
className="
|
||||
select-w
|
||||
custom-select custom-select-sm
|
||||
form-control form-control-sm
|
||||
"
|
||||
>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
entries
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="table-responsive table-shoot mt-3">
|
||||
<table
|
||||
className="table table-centered table-nowrap"
|
||||
style={{ border: '1px solid' }}
|
||||
>
|
||||
<thead className="thead-info" style={{ background: 'rgb(140, 213, 213)' }}>
|
||||
<tr>
|
||||
<th className="text-start">State Name</th>
|
||||
{/* <th className="text-start">State Code (GST)</th> */}
|
||||
<th className="text-start">Created On</th>
|
||||
<th className="text-start">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!loading && showData.length === 0 && (
|
||||
<tr className="text-center">
|
||||
<td colSpan="6">
|
||||
<h5>No Data Available</h5>
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{loading ? (
|
||||
<tr>
|
||||
<td className="text-center" colSpan="6">
|
||||
Loading...
|
||||
</td>
|
||||
</tr>
|
||||
) : (
|
||||
showData.map((city, i) => {
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td className="text-start">{city.state_name}</td>
|
||||
{/* <td className="text-start">{city.state_code}</td> */}
|
||||
<td className="text-start">
|
||||
{new Date(city.createdAt).toLocaleString('en-IN', {
|
||||
weekday: 'short',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
hour12: true,
|
||||
})}
|
||||
</td>
|
||||
|
||||
<td className="text-start">
|
||||
<Link to={`/states/edit/${city._id}`}>
|
||||
<button
|
||||
style={{ color: 'white', margin: '0 1rem' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-primary btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
ml-2
|
||||
"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</Link>
|
||||
<Link
|
||||
to={'#'}
|
||||
style={{
|
||||
margin: '1rem',
|
||||
}}
|
||||
>
|
||||
<button
|
||||
style={{ color: 'white' }}
|
||||
type="button"
|
||||
className="
|
||||
btn btn-danger btn-sm
|
||||
waves-effect waves-light
|
||||
btn-table
|
||||
ml-2
|
||||
|
||||
"
|
||||
onClick={() => {
|
||||
handleDelete(city._id)
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div className="row mt-20">
|
||||
<div className="col-sm-12 col-md-6 mb-20">
|
||||
<div
|
||||
className="dataTables_info"
|
||||
id="datatable_info"
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
>
|
||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{' '}
|
||||
{Math.min(currentPage * itemPerPage, statesData.length)} of{' '}
|
||||
{statesData.length} entries
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-sm-12 col-md-6">
|
||||
<div className="d-flex">
|
||||
<ul className="pagination ms-auto">
|
||||
<li
|
||||
className={
|
||||
currentPage === 1
|
||||
? 'paginate_button page-item previous disabled'
|
||||
: 'paginate_button page-item previous'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
Previous
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(currentPage - 1 < 1) && (
|
||||
<li className="paginate_button page-item">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={(e) => setCurrentPage((prev) => prev - 1)}
|
||||
>
|
||||
{currentPage - 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li className="paginate_button page-item active">
|
||||
<span className="page-link" style={{ cursor: 'pointer' }}>
|
||||
{currentPage}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
{!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
statesData.length - 1
|
||||
) && (
|
||||
<li className="paginate_button page-item ">
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => {
|
||||
setCurrentPage((prev) => prev + 1)
|
||||
}}
|
||||
>
|
||||
{currentPage + 1}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
|
||||
<li
|
||||
className={
|
||||
!(
|
||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
||||
statesData.length - 1
|
||||
)
|
||||
? 'paginate_button page-item next'
|
||||
: 'paginate_button page-item next disabled'
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="page-link"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={() => setCurrentPage((prev) => prev + 1)}
|
||||
>
|
||||
Next
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default States
|
@ -1,20 +1,122 @@
|
||||
import React, { lazy } from 'react'
|
||||
|
||||
|
||||
import axios from "axios";
|
||||
import { useEffect, useState, useCallback, useMemo } from "react";
|
||||
import { isAutheticated } from "../../auth.js";
|
||||
|
||||
const WidgetsDropdown = lazy(() => import('../widgets/WidgetsDropdown.js'))
|
||||
const WidgetsBrand = lazy(() => import('../widgets/WidgetsBrand.js'))
|
||||
|
||||
|
||||
const Dashboard = () => {
|
||||
const random = (min, max) => {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||
//1 st
|
||||
const [users, setUsers] = useState([])
|
||||
const token = isAutheticated();
|
||||
|
||||
const getAllUsers = useCallback(async () => {
|
||||
let res = await axios.get(
|
||||
`/api/v1/admin/users`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
// console.log(res.data)
|
||||
setUsers(res.data.users)
|
||||
|
||||
|
||||
}, [token]);
|
||||
// //2nd
|
||||
// const [category, setCategory] = useState([])
|
||||
// const getAllCategory = useCallback(async () => {
|
||||
// let res = await axios.get(
|
||||
// `/api/category/getAll`,
|
||||
// {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
// // console.log(res.data.category[0].image.url)
|
||||
// setCategory(res.data.category)
|
||||
// }, [token]);
|
||||
|
||||
// //3 requiment
|
||||
// const [requirement, setRequirement] = useState([])
|
||||
// // console.log(token)
|
||||
// const getRequirement = useCallback(async () => {
|
||||
// let res = await axios.get(
|
||||
// `/api/requirement/getAll`,
|
||||
// {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
|
||||
// setRequirement(res.data.Requirement)
|
||||
|
||||
// }, [token]);
|
||||
// //4 news
|
||||
// const [news, setNews] = useState([])
|
||||
|
||||
// const getNews = useCallback(async () => {
|
||||
// let res = await axios.get(
|
||||
// `/api/news/getAll`,
|
||||
// {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
|
||||
// setNews(res.data.news)
|
||||
|
||||
|
||||
// }, [token]);
|
||||
// //5 offers
|
||||
// const [offer, setOffer] = useState([])
|
||||
|
||||
// const getOffer = useCallback(async () => {
|
||||
// let res = await axios.get(
|
||||
// `/api/offer/getAll`,
|
||||
// {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
// // console.log(res.data)
|
||||
// setOffer(res.data.offer)
|
||||
|
||||
|
||||
// }, [token]);
|
||||
// //6 event
|
||||
// const [event, setEvent] = useState([])
|
||||
// const getEvent = useCallback(async () => {
|
||||
// let res = await axios.get(
|
||||
// `/api/event/getAll`,
|
||||
// {
|
||||
// headers: {
|
||||
// Authorization: `Bearer ${token}`,
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
// // console.log(res.data)
|
||||
// setEvent(res.data.Event)
|
||||
|
||||
|
||||
// }, [token]);
|
||||
// useEffect(() => {
|
||||
// getAllUsers();
|
||||
// getAllCategory()
|
||||
// getRequirement()
|
||||
// getNews()
|
||||
// getOffer()
|
||||
// getEvent()
|
||||
// }, [getAllUsers, getAllCategory, getRequirement, getNews, getOffer, getEvent]);
|
||||
return (
|
||||
<>
|
||||
<WidgetsDropdown />
|
||||
<WidgetsDropdown users={users} />
|
||||
|
||||
</>
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import {
|
||||
CButton,
|
||||
CCard,
|
||||
@ -15,42 +15,127 @@ import {
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilLockLocked, cilUser } from '@coreui/icons'
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import { useState } from 'react'
|
||||
import axios from 'axios'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
const Login = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [validForm, setValidForm] = useState(false)
|
||||
const [auth, setAuth] = useState({
|
||||
email: "",
|
||||
password: ""
|
||||
});
|
||||
const history = useHistory();
|
||||
const [errors, setErrors] = useState({
|
||||
emailError: '',
|
||||
passwordError: '',
|
||||
|
||||
const handleChange = (e) => (event) => {
|
||||
setAuth({ ...auth, [e]: event.target.value });
|
||||
};
|
||||
})
|
||||
const validEmailRegex = RegExp(
|
||||
/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i,
|
||||
)
|
||||
const validPasswordRegex = RegExp(/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\w\s]).{7,}$/)
|
||||
const history = useNavigate();
|
||||
// const handleChange = (e) => (event) => {
|
||||
|
||||
// setAuth({ ...auth, [e]: event.target.value });
|
||||
// };
|
||||
const validateForm = () => {
|
||||
let valid = true
|
||||
Object.values(errors).forEach((val) => {
|
||||
if (val.length > 0) {
|
||||
valid = false
|
||||
return false
|
||||
}
|
||||
})
|
||||
Object.values(auth).forEach((val) => {
|
||||
if (val.length <= 0) {
|
||||
valid = false
|
||||
return false
|
||||
}
|
||||
})
|
||||
return valid
|
||||
}
|
||||
|
||||
//cheking email and password
|
||||
useEffect(() => {
|
||||
if (validateForm()) {
|
||||
setValidForm(true)
|
||||
} else {
|
||||
setValidForm(false)
|
||||
}
|
||||
}, [errors])
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target
|
||||
|
||||
switch (name) {
|
||||
case 'email':
|
||||
setErrors({
|
||||
...errors,
|
||||
emailError: validEmailRegex.test(value) ? '' : 'Email is not valid!',
|
||||
})
|
||||
|
||||
break
|
||||
case 'password':
|
||||
setErrors((errors) => ({
|
||||
...errors,
|
||||
passwordError: validPasswordRegex.test(value)
|
||||
? ''
|
||||
: 'Password Shoud Be 8 Characters Long, Atleast One Uppercase, Atleast One Lowercase,Atleast One Digit, Atleast One Special Character',
|
||||
}))
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
setAuth({ ...auth, [name]: value })
|
||||
}
|
||||
|
||||
const Login = async () => {
|
||||
const res = await axios.post("/api/user/login/", auth);
|
||||
if (!(auth.email && auth.password)) {
|
||||
|
||||
return swal('Error!', 'All fields are required', 'error')
|
||||
}
|
||||
setLoading({ loading: true })
|
||||
try {
|
||||
const res = await axios.post("/api/v1/user/login/", auth);
|
||||
if (res.data.success == true) {
|
||||
localStorage.setItem("authToken", res.data.token)
|
||||
console.log(res.data)
|
||||
localStorage.setItem("auth", JSON.stringify({
|
||||
user: res.data.user,
|
||||
token: res.data.token,
|
||||
let response = await axios.get(`/api/v1/user/details`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${res.data.token}`,
|
||||
},
|
||||
})
|
||||
// console.log(response.data)
|
||||
const data = response.data
|
||||
if (data.user.role === 'admin') {
|
||||
history('/dashboard')
|
||||
setLoading(false);
|
||||
window.location.reload()
|
||||
}
|
||||
else {
|
||||
swal('Error!', 'please try with admin credential!!', 'error')
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
|
||||
}));
|
||||
history.push('/dashboard')
|
||||
|
||||
}
|
||||
else {
|
||||
if (res.data.status === "blocked")
|
||||
alert(res.data.message)
|
||||
else
|
||||
alert("Invalid Credentials");
|
||||
setLoading(false);
|
||||
|
||||
swal('Error!', 'Invalid Credentials', 'error')
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
|
||||
swal('Error!', 'Invalid Credentials', 'error')
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-light min-vh-100 d-flex flex-row align-items-center">
|
||||
<CContainer>
|
||||
@ -61,28 +146,37 @@ const Login = () => {
|
||||
<CCardBody>
|
||||
<CForm>
|
||||
<h1>Login</h1>
|
||||
<p className="text-medium-emphasis">Sign In to Your CMP Dashboard Account.</p>
|
||||
<p className="text-medium-emphasis">Sign In to Your ATP Dashboard Account.</p>
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
</CInputGroupText>
|
||||
<CFormInput placeholder="Email" onChange={handleChange("email")} autoComplete="email" />
|
||||
<CFormInput type="email" placeholder="Email" onChange={handleChange} value={auth.email} name="email" autoComplete="email" />
|
||||
</CInputGroup>
|
||||
{errors.emailError && (
|
||||
<p className="text-center py-2 text-danger">{errors.emailError}</p>
|
||||
)}
|
||||
<CInputGroup className="mb-4">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
<CFormInput
|
||||
type="password"
|
||||
onChange={handleChange("password")}
|
||||
name="password"
|
||||
value={auth.password}
|
||||
onChange={handleChange}
|
||||
placeholder="Password"
|
||||
autoComplete="current-password"
|
||||
/>
|
||||
</CInputGroup>
|
||||
|
||||
{errors.passwordError && (
|
||||
<p className="text-center py-2 text-danger">{errors.passwordError}</p>
|
||||
)}
|
||||
<CButton color="primary" className="px-4" disabled={!validForm} onClick={Login}>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Login"}
|
||||
|
||||
<CButton color="primary" className="px-4" onClick={Login}>
|
||||
Login
|
||||
</CButton>
|
||||
|
||||
|
||||
@ -93,11 +187,11 @@ const Login = () => {
|
||||
</Link>
|
||||
<br />
|
||||
|
||||
{/* <CButton color="link" className="px-0">
|
||||
<Link to="/forgot">
|
||||
Forgot password?
|
||||
<CButton color="link" className="px-0">
|
||||
<Link to="/password/forgot">
|
||||
Forgot password.?
|
||||
</Link>
|
||||
</CButton> */}
|
||||
</CButton>
|
||||
|
||||
|
||||
</CForm>
|
||||
@ -118,3 +212,8 @@ const Login = () => {
|
||||
}
|
||||
|
||||
export default Login
|
||||
|
||||
// < Route path = "/" name = "Home" render = {(props) => (
|
||||
// userdata && userdata.role === 'admin' ? <DefaultLayout {...props} /> :
|
||||
// <><Login {...props} /></>
|
||||
// )} />
|
@ -13,35 +13,92 @@ import {
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilLockLocked, cilUser } from '@coreui/icons'
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
import axios from 'axios'
|
||||
import { isAutheticated } from 'src/auth'
|
||||
import Swal from 'sweetalert2'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
const Register = () => {
|
||||
const [oldPassword, setOldPassword] = useState();
|
||||
const [newPassword, setNewPassword] = useState();
|
||||
const [confirmPassword, setConfirmPassword] = useState();
|
||||
const history = useHistory();
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const history = useNavigate();
|
||||
const [user, setUser] = useState({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
})
|
||||
const [errors, setErrors] = useState({
|
||||
confirmPasswordError: '',
|
||||
newPasswordError: '',
|
||||
oldPasswordError: '',
|
||||
|
||||
})
|
||||
const validEmailRegex = RegExp(
|
||||
/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i,
|
||||
)
|
||||
const validPasswordRegex = RegExp(/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^\w\s]).{7,}$/)
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target
|
||||
|
||||
switch (name) {
|
||||
case 'oldPassword':
|
||||
setErrors({
|
||||
...errors,
|
||||
oldPasswordError: validPasswordRegex.test(value)
|
||||
? ''
|
||||
: 'Password Shoud Be 8 Characters Long, Atleast One Uppercase, Atleast One Lowercase,Atleast One Digit, Atleast One Special Character',
|
||||
})
|
||||
|
||||
break
|
||||
case 'newPassword':
|
||||
setErrors({
|
||||
...errors,
|
||||
newPasswordError: validPasswordRegex.test(value)
|
||||
? ''
|
||||
: 'Password Shoud Be 8 Characters Long, Atleast One Uppercase, Atleast One Lowercase,Atleast One Digit, Atleast One Special Character',
|
||||
})
|
||||
|
||||
break
|
||||
case 'confirmPassword':
|
||||
setErrors((errors) => ({
|
||||
...errors,
|
||||
confirmPasswordError: validPasswordRegex.test(value)
|
||||
? ''
|
||||
: 'Password Shoud Be 8 Characters Long, Atleast One Uppercase, Atleast One Lowercase,Atleast One Digit, Atleast One Special Character',
|
||||
}))
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
setUser({ ...user, [name]: value })
|
||||
}
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!(user.oldPassword && user.newPassword && user.confirmPassword)) {
|
||||
|
||||
return swal('Error!', 'All fields are required', 'error')
|
||||
}
|
||||
if (!(user.newPassword.length >= 8)) {
|
||||
|
||||
return swal('Error!', 'All fields are required', 'error');
|
||||
}
|
||||
const token = localStorage.getItem("authToken")
|
||||
//console.log(token)
|
||||
if (newPassword == confirmPassword) {
|
||||
let res = await axios.put('/api/user/update/password',
|
||||
setLoading({ loading: true })
|
||||
if (user.newPassword == user.confirmPassword) {
|
||||
let res = await axios.put('/api/v1/user/password/update',
|
||||
{
|
||||
oldPassword
|
||||
, newPassword,
|
||||
confirmPassword
|
||||
...user
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
}
|
||||
})
|
||||
console.log(res)
|
||||
if (res) {
|
||||
|
||||
// console.log(res.data.success)
|
||||
if (res.data.success == true) {
|
||||
Swal.fire({
|
||||
title: 'Done',
|
||||
text: 'Password Changed',
|
||||
@ -50,12 +107,14 @@ const Register = () => {
|
||||
confirmButtonColor: '#303c54',
|
||||
iconColor: '#303c54'
|
||||
}).then(() => {
|
||||
history.push('/dashboard')
|
||||
history('/dashboard')
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
setLoading(false);
|
||||
} else {
|
||||
alert('new password and confirm password are not matched')
|
||||
swal('Error!', 'New Password And Confirm Password is Not Match !', 'error')
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
}
|
||||
@ -74,31 +133,56 @@ const Register = () => {
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
<CFormInput placeholder="Old Password" autoComplete="email" onChange={(e) => setOldPassword(e.target.value)} />
|
||||
<CFormInput placeholder="Old Password" type="password" value={user.oldPassword}
|
||||
onChange={handleChange}
|
||||
autoComplete="current-password"
|
||||
name="oldPassword" />
|
||||
</CInputGroup>
|
||||
{errors.oldPasswordError && (
|
||||
<p className="text-center py-2 text-danger">{errors.oldPasswordError}</p>
|
||||
)}
|
||||
|
||||
<CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
<CFormInput
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
placeholder=" New Password"
|
||||
|
||||
value={user.newPassword}
|
||||
onChange={handleChange}
|
||||
name="newPassword"
|
||||
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
/>
|
||||
</CInputGroup>
|
||||
{errors.newPasswordError && (
|
||||
<p className="text-center py-2 text-danger">{errors.newPasswordError}</p>
|
||||
)}
|
||||
<CInputGroup className="mb-4">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilLockLocked} />
|
||||
</CInputGroupText>
|
||||
{errors.passwordError && (
|
||||
<p className="text-center py-2 text-danger">{errors.passwordError}</p>
|
||||
)}
|
||||
<CFormInput
|
||||
type="password"
|
||||
placeholder="Confirm password"
|
||||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||
|
||||
placeholder="Confirm password "
|
||||
value={user.confirmPassword}
|
||||
onChange={handleChange}
|
||||
name="confirmPassword"
|
||||
/>
|
||||
</CInputGroup>
|
||||
{errors.confirmPasswordError && (
|
||||
<p className="text-center py-2 text-danger">{errors.confirmPasswordError}</p>
|
||||
)}
|
||||
<div className="d-grid">
|
||||
<CButton color="success" onClick={handleSubmit}>Submit</CButton>
|
||||
<CButton color="success" onClick={handleSubmit}>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Submit"}
|
||||
</CButton>
|
||||
</div>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
|
@ -1,5 +1,9 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react'
|
||||
import axios from 'axios';
|
||||
import ClipLoader from "react-spinners/ClipLoader";
|
||||
|
||||
import {
|
||||
|
||||
CButton,
|
||||
CCard,
|
||||
CCardBody,
|
||||
@ -13,9 +17,41 @@ import {
|
||||
} from '@coreui/react'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilEnvelopeLetter, cilEnvelopeOpen, cilLockLocked, cilUser } from '@coreui/icons'
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import swal from 'sweetalert';
|
||||
|
||||
const ForgotPassword = () => {
|
||||
const navigate = useNavigate()
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [email, setEmail] = useState()
|
||||
// console.log(email)
|
||||
const handleSubmit = async () => {
|
||||
if (email) {
|
||||
try {
|
||||
setLoading(true)
|
||||
|
||||
const res = await axios.post(`/api/v1/user/password/forgot`, { email: email })
|
||||
// console.log(res);
|
||||
if (res.data.success === true) {
|
||||
setLoading(false)
|
||||
// alert("Email Send Successfully! please check your mail for reset password")
|
||||
swal("success!", "Email Send Successfully! please check your Email for new password", "success");
|
||||
navigate("/");
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
swal('Error!', 'Wrong Email ID. Enter valid email to get the password', 'error')
|
||||
setLoading(false)
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
alert("please fill Email field..")
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return <div className="bg-light min-vh-100 d-flex flex-row align-items-center">
|
||||
<CContainer>
|
||||
<CRow className="justify-content-center">
|
||||
@ -24,7 +60,7 @@ const ForgotPassword = () => {
|
||||
<CCardBody className="p-4">
|
||||
<CForm>
|
||||
<h1>Forgot Password?</h1>
|
||||
<p className="text-medium-emphasis"> Enter your email Below we will send you a link to reset your password</p>
|
||||
<p className="text-medium-emphasis"> Enter your email Below, we will send you password in your Email</p>
|
||||
{/* <CInputGroup className="mb-3">
|
||||
<CInputGroupText>
|
||||
<CIcon icon={cilUser} />
|
||||
@ -37,15 +73,20 @@ const ForgotPassword = () => {
|
||||
<CIcon icon={cilEnvelopeOpen} />
|
||||
</CInputGroupText>
|
||||
<CFormInput
|
||||
type="password"
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
autoComplete="email"
|
||||
// value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</CInputGroup>
|
||||
|
||||
<CButton color="dark">Send</CButton>
|
||||
<CButton color="primary" disabled={!email} onClick={() => handleSubmit()}>
|
||||
<ClipLoader loading={loading} size={18} />
|
||||
{!loading && "Send"}
|
||||
</CButton>
|
||||
<Link to='/'>
|
||||
<CButton color="dark" className='ms-2'>Back to Login</CButton>
|
||||
<CButton color="secondary" className='ms-2'>Back to Login</CButton>
|
||||
</Link>
|
||||
</CForm>
|
||||
</CCardBody>
|
||||
|
@ -3,7 +3,7 @@ import { CForm, CCol, CFormLabel, CContainer, CRow, CCardGroup, CCard, CCardBody
|
||||
import { Country, City } from 'country-state-city'
|
||||
import { useState, useEffect } from 'react'
|
||||
import axios from 'axios'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
const NewRegister = () => {
|
||||
const [cities, setCities] = useState([])
|
||||
const [ownerDetails, setOwnerDetails] = useState({
|
||||
@ -14,7 +14,7 @@ const NewRegister = () => {
|
||||
country: 'India',
|
||||
city: ''
|
||||
})
|
||||
const history = useHistory()
|
||||
const history = useNavigate()
|
||||
const [processing, setProcessing] = useState(false)
|
||||
const countries = Country.getAllCountries()
|
||||
useEffect(() => {
|
||||
@ -48,7 +48,7 @@ const NewRegister = () => {
|
||||
|
||||
// token: res.data.token,
|
||||
// }));
|
||||
history.push('/')
|
||||
history('/')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,10 @@ import { getStyle } from '@coreui/utils'
|
||||
import { CChartBar, CChartLine } from '@coreui/react-chartjs'
|
||||
import CIcon from '@coreui/icons-react'
|
||||
import { cilArrowBottom, cilArrowTop, cilOptions } from '@coreui/icons'
|
||||
import { BeatLoader } from 'react-spinners'
|
||||
{/* <BeatLoader color="#36d7b7" /> */ }
|
||||
|
||||
const WidgetsDropdown = () => {
|
||||
const WidgetsDropdown = ({ users }) => {
|
||||
return (
|
||||
<CRow>
|
||||
<CCol sm={6} lg={3}>
|
||||
@ -22,244 +24,39 @@ const WidgetsDropdown = () => {
|
||||
color="primary"
|
||||
value={
|
||||
<>
|
||||
26K{' '}
|
||||
{/* <span className="fs-6 fw-normal">
|
||||
(-12.4% <CIcon icon={cilArrowBottom} />)
|
||||
</span> */}
|
||||
|
||||
{users.length}
|
||||
</>
|
||||
}
|
||||
title="Users"
|
||||
// action={
|
||||
// <CDropdown alignment="end">
|
||||
// <CDropdownToggle color="transparent" caret={false} className="p-0">
|
||||
// <CIcon icon={cilOptions} className="text-high-emphasis-inverse" />
|
||||
// </CDropdownToggle>
|
||||
// <CDropdownMenu>
|
||||
// <CDropdownItem>Action</CDropdownItem>
|
||||
// <CDropdownItem>Another action</CDropdownItem>
|
||||
// <CDropdownItem>Something else here...</CDropdownItem>
|
||||
// <CDropdownItem disabled>Disabled action</CDropdownItem>
|
||||
// </CDropdownMenu>
|
||||
// </CDropdown>
|
||||
// }
|
||||
chart={
|
||||
<CChartLine
|
||||
className="mt-3 mx-3"
|
||||
style={{ height: '70px' }}
|
||||
data={{
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [
|
||||
{
|
||||
label: 'My First dataset',
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: 'rgba(255,255,255,.55)',
|
||||
pointBackgroundColor: getStyle('--cui-primary'),
|
||||
data: [65, 59, 84, 84, 51, 55, 40],
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false,
|
||||
drawBorder: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
min: 30,
|
||||
max: 89,
|
||||
display: false,
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 1,
|
||||
tension: 0.4,
|
||||
},
|
||||
point: {
|
||||
radius: 4,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 4,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</CCol>
|
||||
<CCol sm={6} lg={3}>
|
||||
<CWidgetStatsA
|
||||
className="mb-4"
|
||||
color="info"
|
||||
value={
|
||||
<>
|
||||
$6.200{' '}
|
||||
{/* <span className="fs-6 fw-normal">
|
||||
(40.9% <CIcon icon={cilArrowTop} />)
|
||||
</span> */}
|
||||
</>
|
||||
}
|
||||
title="Income"
|
||||
// action={
|
||||
// <CDropdown alignment="end">
|
||||
// <CDropdownToggle color="transparent" caret={false} className="p-0">
|
||||
// <CIcon icon={cilOptions} className="text-high-emphasis-inverse" />
|
||||
// </CDropdownToggle>
|
||||
// <CDropdownMenu>
|
||||
// <CDropdownItem>Action</CDropdownItem>
|
||||
// <CDropdownItem>Another action</CDropdownItem>
|
||||
// <CDropdownItem>Something else here...</CDropdownItem>
|
||||
// <CDropdownItem disabled>Disabled action</CDropdownItem>
|
||||
// </CDropdownMenu>
|
||||
// </CDropdown>
|
||||
// }
|
||||
chart={
|
||||
<CChartLine
|
||||
className="mt-3 mx-3"
|
||||
style={{ height: '70px' }}
|
||||
data={{
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [
|
||||
{
|
||||
label: 'My First dataset',
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: 'rgba(255,255,255,.55)',
|
||||
pointBackgroundColor: getStyle('--cui-info'),
|
||||
data: [1, 18, 9, 17, 34, 22, 11],
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false,
|
||||
drawBorder: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
min: -9,
|
||||
max: 39,
|
||||
display: false,
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 1,
|
||||
},
|
||||
point: {
|
||||
radius: 4,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 4,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
title="Total Users"
|
||||
|
||||
/>
|
||||
</CCol>
|
||||
{/* <CCol sm={6} lg={3}>
|
||||
<CWidgetStatsA
|
||||
className="mb-4"
|
||||
color="info"
|
||||
value={
|
||||
<>
|
||||
{category.length}
|
||||
</>
|
||||
}
|
||||
title="Total Categories"
|
||||
|
||||
/>
|
||||
</CCol>
|
||||
<CCol sm={6} lg={3}>
|
||||
<CWidgetStatsA
|
||||
className="mb-4"
|
||||
color="warning"
|
||||
value={
|
||||
<>
|
||||
2.49{' '}
|
||||
<span className="fs-6 fw-normal">
|
||||
(84.7% <CIcon icon={cilArrowTop} />)
|
||||
</span>
|
||||
{requirement.length}
|
||||
|
||||
</>
|
||||
}
|
||||
title="Conversion Rate"
|
||||
action={
|
||||
<CDropdown alignment="end">
|
||||
<CDropdownToggle color="transparent" caret={false} className="p-0">
|
||||
<CIcon icon={cilOptions} className="text-high-emphasis-inverse" />
|
||||
</CDropdownToggle>
|
||||
<CDropdownMenu>
|
||||
<CDropdownItem>Action</CDropdownItem>
|
||||
<CDropdownItem>Another action</CDropdownItem>
|
||||
<CDropdownItem>Something else here...</CDropdownItem>
|
||||
<CDropdownItem disabled>Disabled action</CDropdownItem>
|
||||
</CDropdownMenu>
|
||||
</CDropdown>
|
||||
}
|
||||
chart={
|
||||
<CChartLine
|
||||
className="mt-3"
|
||||
style={{ height: '70px' }}
|
||||
data={{
|
||||
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
|
||||
datasets: [
|
||||
{
|
||||
label: 'My First dataset',
|
||||
backgroundColor: 'rgba(255,255,255,.2)',
|
||||
borderColor: 'rgba(255,255,255,.55)',
|
||||
data: [78, 81, 80, 45, 34, 12, 40],
|
||||
fill: true,
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: {
|
||||
display: false,
|
||||
},
|
||||
y: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 2,
|
||||
tension: 0.4,
|
||||
},
|
||||
point: {
|
||||
radius: 0,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 4,
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
title="Requirements"
|
||||
|
||||
/>
|
||||
</CCol>
|
||||
<CCol sm={6} lg={3}>
|
||||
@ -268,92 +65,42 @@ const WidgetsDropdown = () => {
|
||||
color="danger"
|
||||
value={
|
||||
<>
|
||||
44K{' '}
|
||||
<span className="fs-6 fw-normal">
|
||||
(-23.6% <CIcon icon={cilArrowBottom} />)
|
||||
</span>
|
||||
{news.length}
|
||||
|
||||
</>
|
||||
}
|
||||
title="Sessions"
|
||||
action={
|
||||
<CDropdown alignment="end">
|
||||
<CDropdownToggle color="transparent" caret={false} className="p-0">
|
||||
<CIcon icon={cilOptions} className="text-high-emphasis-inverse" />
|
||||
</CDropdownToggle>
|
||||
<CDropdownMenu>
|
||||
<CDropdownItem>Action</CDropdownItem>
|
||||
<CDropdownItem>Another action</CDropdownItem>
|
||||
<CDropdownItem>Something else here...</CDropdownItem>
|
||||
<CDropdownItem disabled>Disabled action</CDropdownItem>
|
||||
</CDropdownMenu>
|
||||
</CDropdown>
|
||||
}
|
||||
chart={
|
||||
<CChartBar
|
||||
className="mt-3 mx-3"
|
||||
style={{ height: '70px' }}
|
||||
data={{
|
||||
labels: [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
],
|
||||
datasets: [
|
||||
{
|
||||
label: 'My First dataset',
|
||||
backgroundColor: 'rgba(255,255,255,.2)',
|
||||
borderColor: 'rgba(255,255,255,.55)',
|
||||
data: [78, 81, 80, 45, 34, 12, 40, 85, 65, 23, 12, 98, 34, 84, 67, 82],
|
||||
barPercentage: 0.6,
|
||||
},
|
||||
],
|
||||
}}
|
||||
options={{
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
display: false,
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
display: false,
|
||||
drawBorder: false,
|
||||
drawTicks: false,
|
||||
},
|
||||
ticks: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
title="Total News"
|
||||
|
||||
/>
|
||||
</CCol>
|
||||
<CCol sm={6} lg={3}>
|
||||
<CWidgetStatsA
|
||||
className="mb-4"
|
||||
color="success"
|
||||
value={
|
||||
<>
|
||||
{offer.length}
|
||||
|
||||
</>
|
||||
}
|
||||
title="Total Offers"
|
||||
|
||||
/>
|
||||
</CCol> */}
|
||||
</CCol>
|
||||
<CCol sm={6} lg={3}>
|
||||
<CWidgetStatsA
|
||||
className="mb-4"
|
||||
color="dark"
|
||||
value={
|
||||
<>
|
||||
{event.length}
|
||||
|
||||
</>
|
||||
}
|
||||
title="Total Events"
|
||||
|
||||
/> */}
|
||||
{/* </CCol> */}
|
||||
</CRow>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user