updates and removed on the dead codes
This commit is contained in:
18
src/App.js
18
src/App.js
@@ -2,7 +2,6 @@
|
|||||||
import Routes from 'routes';
|
import Routes from 'routes';
|
||||||
import ThemeCustomization from 'themes';
|
import ThemeCustomization from 'themes';
|
||||||
import Locales from 'components/Locales';
|
import Locales from 'components/Locales';
|
||||||
// import RTLLayout from 'components/RTLLayout';
|
|
||||||
import ScrollTop from 'components/ScrollTop';
|
import ScrollTop from 'components/ScrollTop';
|
||||||
import Snackbar from 'components/@extended/Snackbar';
|
import Snackbar from 'components/@extended/Snackbar';
|
||||||
import Notistack from 'components/third-party/Notistack';
|
import Notistack from 'components/third-party/Notistack';
|
||||||
@@ -12,9 +11,6 @@ import { generateToken, initFirebaseNotificationListener } from 'firebase_notifi
|
|||||||
import InternetStatus from 'components/updateNetworkStatus';
|
import InternetStatus from 'components/updateNetworkStatus';
|
||||||
import useInactivityLogout from 'hooks/useInactivityLogout';
|
import useInactivityLogout from 'hooks/useInactivityLogout';
|
||||||
|
|
||||||
// auth-provider
|
|
||||||
// import { JWTProvider as AuthProvider } from 'contexts/JWTContext';
|
|
||||||
|
|
||||||
// ==============================|| APP - THEME, ROUTER, LOCAL ||============================== //
|
// ==============================|| APP - THEME, ROUTER, LOCAL ||============================== //
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@@ -45,21 +41,13 @@ const App = () => {
|
|||||||
<>
|
<>
|
||||||
<ThemeCustomization>
|
<ThemeCustomization>
|
||||||
<InternetStatus />
|
<InternetStatus />
|
||||||
{/* <RTLLayout> */}
|
|
||||||
<Locales>
|
<Locales>
|
||||||
<ScrollTop>
|
<ScrollTop>
|
||||||
{/* <AuthProvider> */}
|
<Notistack>
|
||||||
<>
|
<AppContent />
|
||||||
<Notistack>
|
</Notistack>
|
||||||
{/* <Routes />
|
|
||||||
<Snackbar /> */}
|
|
||||||
<AppContent />
|
|
||||||
</Notistack>
|
|
||||||
</>
|
|
||||||
{/* </AuthProvider> */}
|
|
||||||
</ScrollTop>
|
</ScrollTop>
|
||||||
</Locales>
|
</Locales>
|
||||||
{/* </RTLLayout> */}
|
|
||||||
</ThemeCustomization>
|
</ThemeCustomization>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, CircularProgress, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// ==============================|| PROGRESS - CIRCULAR LABEL ||============================== //
|
|
||||||
|
|
||||||
export default function CircularWithLabel({ value, ...others }) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ position: 'relative', display: 'inline-flex' }}>
|
|
||||||
<CircularProgress variant="determinate" value={value} {...others} />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
right: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="caption" component="div" color="text.secondary">{`${Math.round(value)}%`}</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
CircularWithLabel.propTypes = {
|
|
||||||
value: PropTypes.number
|
|
||||||
};
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, CircularProgress, Typography, circularProgressClasses } from '@mui/material';
|
|
||||||
|
|
||||||
// ==============================|| PROGRESS - CIRCULAR PATH ||============================== //
|
|
||||||
|
|
||||||
export default function CircularWithPath({ value, size, variant, thickness, showLabel, pathColor, sx, ...others }) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ position: 'relative', display: 'inline-flex' }}>
|
|
||||||
<CircularProgress
|
|
||||||
variant="determinate"
|
|
||||||
sx={{ color: pathColor ? pathColor : 'grey.200' }}
|
|
||||||
size={size}
|
|
||||||
thickness={thickness}
|
|
||||||
{...others}
|
|
||||||
value={100}
|
|
||||||
/>
|
|
||||||
{showLabel && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
top: 0,
|
|
||||||
left: 0,
|
|
||||||
bottom: 0,
|
|
||||||
right: 0,
|
|
||||||
position: 'absolute',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="caption" component="div" color="text.secondary">
|
|
||||||
{value ? `${Math.round(value)}%` : '0%'}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
<CircularProgress
|
|
||||||
variant={variant}
|
|
||||||
sx={{
|
|
||||||
...sx,
|
|
||||||
position: 'absolute',
|
|
||||||
left: 0,
|
|
||||||
[`& .${circularProgressClasses.circle}`]: {
|
|
||||||
strokeLinecap: 'round'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
size={size}
|
|
||||||
thickness={thickness}
|
|
||||||
value={value}
|
|
||||||
{...others}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
CircularWithPath.propTypes = {
|
|
||||||
value: PropTypes.number,
|
|
||||||
size: PropTypes.number,
|
|
||||||
variant: PropTypes.string,
|
|
||||||
thickness: PropTypes.number,
|
|
||||||
showLabel: PropTypes.bool,
|
|
||||||
pathColor: PropTypes.string,
|
|
||||||
sx: PropTypes.array,
|
|
||||||
others: PropTypes.array
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, LinearProgress } from '@mui/material';
|
|
||||||
|
|
||||||
// ==============================|| PROGRESS - LINEAR ICON ||============================== //
|
|
||||||
|
|
||||||
export default function LinearWithIcon({ icon, value, ...others }) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
||||||
<Box sx={{ width: '100%', mr: 1 }}>
|
|
||||||
<LinearProgress variant="determinate" value={value} {...others} />
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ minWidth: 35 }}>{icon}</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearWithIcon.propTypes = {
|
|
||||||
icon: PropTypes.node,
|
|
||||||
value: PropTypes.number
|
|
||||||
};
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, LinearProgress, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// ==============================|| PROGRESS - LINEAR WITH LABEL ||============================== //
|
|
||||||
|
|
||||||
export default function LinearWithLabel({ value, ...others }) {
|
|
||||||
return (
|
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
||||||
<Box sx={{ width: '100%', mr: 1 }}>
|
|
||||||
<LinearProgress variant="determinate" value={value} {...others} />
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ minWidth: 35 }}>
|
|
||||||
<Typography variant="body2" color="text.secondary">{`${Math.round(value)}%`}</Typography>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearWithLabel.propTypes = {
|
|
||||||
value: PropTypes.number
|
|
||||||
};
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { CacheProvider } from '@emotion/react';
|
|
||||||
import createCache from '@emotion/cache';
|
|
||||||
|
|
||||||
// third-party
|
|
||||||
import rtlPlugin from 'stylis-plugin-rtl';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import { ThemeDirection } from 'config';
|
|
||||||
import useConfig from 'hooks/useConfig';
|
|
||||||
|
|
||||||
// ==============================|| RTL LAYOUT ||============================== //
|
|
||||||
|
|
||||||
const RTLLayout = ({ children }) => {
|
|
||||||
const { themeDirection } = useConfig();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
document.dir = themeDirection;
|
|
||||||
}, [themeDirection]);
|
|
||||||
|
|
||||||
const cacheRtl = createCache({
|
|
||||||
key: themeDirection === ThemeDirection.RTL ? 'rtl' : 'css',
|
|
||||||
prepend: true,
|
|
||||||
stylisPlugins: themeDirection === ThemeDirection.RTL ? [rtlPlugin] : []
|
|
||||||
});
|
|
||||||
|
|
||||||
return <CacheProvider value={cacheRtl}>{children}</CacheProvider>;
|
|
||||||
};
|
|
||||||
|
|
||||||
RTLLayout.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RTLLayout;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// material-ui
|
|
||||||
import { styled } from '@mui/material/styles';
|
|
||||||
|
|
||||||
const ScrollX = styled('div')({
|
|
||||||
width: '100%',
|
|
||||||
overflowX: 'auto',
|
|
||||||
display: 'block'
|
|
||||||
});
|
|
||||||
|
|
||||||
export default ScrollX;
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, Grid, Link, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { GlobalOutlined, NodeExpandOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| COMPONENTS - BREADCRUMBS ||============================== //
|
|
||||||
|
|
||||||
const ComponentHeader = ({ title, caption, directory, link }) => (
|
|
||||||
<Box sx={{ pl: 3 }}>
|
|
||||||
<Stack spacing={1.25}>
|
|
||||||
<Typography variant="h2">{title}</Typography>
|
|
||||||
{caption && (
|
|
||||||
<Typography variant="h6" color="textSecondary">
|
|
||||||
{caption}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
<Grid container spacing={0.75} sx={{ mt: 1.75 }}>
|
|
||||||
{directory && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography variant="caption" color="textSecondary">
|
|
||||||
<NodeExpandOutlined style={{ marginRight: 10 }} />
|
|
||||||
{directory}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{link && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Link variant="caption" color="primary" href={link} target="_blank">
|
|
||||||
<GlobalOutlined style={{ marginRight: 10 }} />
|
|
||||||
{link}
|
|
||||||
</Link>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
|
|
||||||
ComponentHeader.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
caption: PropTypes.string,
|
|
||||||
directory: PropTypes.string,
|
|
||||||
link: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ComponentHeader;
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { Fab, Badge } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
|
|
||||||
// assets
|
|
||||||
|
|
||||||
// ==============================|| CART ITEMS - FLOATING BUTTON ||============================== //
|
|
||||||
|
|
||||||
const FloatingCart = ({ element, count = 0, onClick, sx }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
// const cart = useSelector((state) => state.cart);
|
|
||||||
// const totalQuantity = sum(cart.checkout.products.map((item) => item.quantity));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fab
|
|
||||||
// component={Link}
|
|
||||||
// to="/apps/e-commerce/checkout"
|
|
||||||
onClick={onClick} // ← important
|
|
||||||
size="large"
|
|
||||||
sx={{
|
|
||||||
top: '75%',
|
|
||||||
position: 'fixed',
|
|
||||||
right: 0,
|
|
||||||
zIndex: theme.zIndex.speedDial,
|
|
||||||
boxShadow: theme.customShadows.primary,
|
|
||||||
bgcolor: 'primary.lighter',
|
|
||||||
color: 'primary.main',
|
|
||||||
borderRadius: '25%',
|
|
||||||
borderTopRightRadius: 0,
|
|
||||||
borderBottomRightRadius: 0,
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: 'primary.100',
|
|
||||||
boxShadow: theme.customShadows.primary
|
|
||||||
},
|
|
||||||
'&:focus-visible': {
|
|
||||||
outline: `2px solid ${theme.palette.primary.dark}`,
|
|
||||||
outlineOffset: 2
|
|
||||||
},
|
|
||||||
...sx
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Badge showZero badgeContent={count} color="error">
|
|
||||||
{element}
|
|
||||||
</Badge>
|
|
||||||
</Fab>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FloatingCart;
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { Box, Button, CardContent, CardMedia, Chip, Divider, Grid, Rating, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import SkeletonProductPlaceholder from 'components/cards/skeleton/ProductPlaceholder';
|
|
||||||
import { useDispatch, useSelector } from 'store';
|
|
||||||
import { addProduct } from 'store/reducers/cart';
|
|
||||||
import { openSnackbar } from 'store/reducers/snackbar';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { HeartOutlined, HeartFilled } from '@ant-design/icons';
|
|
||||||
|
|
||||||
const prodImage = require.context('assets/images/e-commerce', true);
|
|
||||||
|
|
||||||
// ==============================|| PRODUCT CARD ||============================== //
|
|
||||||
|
|
||||||
const ProductCard = ({ id, color, name, brand, offer, isStock, image, description, offerPrice, salePrice, rating }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const prodProfile = image && prodImage(`./${image}`);
|
|
||||||
const [productRating] = useState(rating);
|
|
||||||
const [wishlisted, setWishlisted] = useState(false);
|
|
||||||
const cart = useSelector((state) => state.cart);
|
|
||||||
|
|
||||||
const addCart = () => {
|
|
||||||
dispatch(addProduct({ id, name, image, salePrice, offerPrice, color, size: 8, quantity: 1, description }, cart.checkout.products));
|
|
||||||
dispatch(
|
|
||||||
openSnackbar({
|
|
||||||
open: true,
|
|
||||||
message: 'Add To Cart Success',
|
|
||||||
variant: 'alert',
|
|
||||||
alert: {
|
|
||||||
color: 'success'
|
|
||||||
},
|
|
||||||
close: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const addToFavourite = () => {
|
|
||||||
setWishlisted(!wishlisted);
|
|
||||||
dispatch(
|
|
||||||
openSnackbar({
|
|
||||||
open: true,
|
|
||||||
message: 'Added to favourites',
|
|
||||||
variant: 'alert',
|
|
||||||
alert: {
|
|
||||||
color: 'success'
|
|
||||||
},
|
|
||||||
close: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState(true);
|
|
||||||
useEffect(() => {
|
|
||||||
setLoading(false);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{isLoading ? (
|
|
||||||
<SkeletonProductPlaceholder />
|
|
||||||
) : (
|
|
||||||
<MainCard
|
|
||||||
content={false}
|
|
||||||
boxShadow
|
|
||||||
sx={{
|
|
||||||
'&:hover': {
|
|
||||||
transform: 'scale3d(1.02, 1.02, 1)',
|
|
||||||
transition: 'all .4s ease-in-out'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ width: 250, m: 'auto' }}>
|
|
||||||
<CardMedia
|
|
||||||
sx={{ height: 250, textDecoration: 'none', opacity: isStock ? 1 : 0.25 }}
|
|
||||||
image={prodProfile}
|
|
||||||
component={Link}
|
|
||||||
to={`/apps/e-commerce/product-details/${id}`}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
alignItems="center"
|
|
||||||
justifyContent="space-between"
|
|
||||||
sx={{ width: '100%', position: 'absolute', top: 0, pt: 1.75, pl: 2, pr: 1 }}
|
|
||||||
>
|
|
||||||
{!isStock && <Chip variant="light" color="error" size="small" label="Sold out" />}
|
|
||||||
{offer && <Chip label={offer} variant="combined" color="success" size="small" />}
|
|
||||||
<IconButton color="secondary" sx={{ ml: 'auto', '&:hover': { background: 'transparent' } }} onClick={addToFavourite}>
|
|
||||||
{wishlisted ? (
|
|
||||||
<HeartFilled style={{ fontSize: '1.15rem', color: theme.palette.error.main }} />
|
|
||||||
) : (
|
|
||||||
<HeartOutlined style={{ fontSize: '1.15rem' }} />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
<Divider />
|
|
||||||
<CardContent sx={{ p: 2 }}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack>
|
|
||||||
<Typography
|
|
||||||
component={Link}
|
|
||||||
to={`/apps/e-commerce/product-details/${id}`}
|
|
||||||
color="textPrimary"
|
|
||||||
variant="h5"
|
|
||||||
sx={{
|
|
||||||
overflow: 'hidden',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
display: 'block',
|
|
||||||
textDecoration: 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="h6" color="textSecondary">
|
|
||||||
{brand}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="flex-end" flexWrap="wrap" rowGap={1.75}>
|
|
||||||
<Stack>
|
|
||||||
<Stack direction="row" spacing={1} alignItems="center">
|
|
||||||
<Typography variant="h5">${offerPrice}</Typography>
|
|
||||||
{salePrice && (
|
|
||||||
<Typography variant="h6" color="textSecondary" sx={{ textDecoration: 'line-through' }}>
|
|
||||||
${salePrice}
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="row" alignItems="flex-start">
|
|
||||||
<Rating precision={0.5} name="size-small" value={productRating} size="small" readOnly />
|
|
||||||
<Typography variant="caption">({productRating?.toFixed(1)})</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<Button variant="contained" onClick={addCart} disabled={!isStock}>
|
|
||||||
{!isStock ? 'Sold Out' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</CardContent>
|
|
||||||
</MainCard>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ProductCard.propTypes = {
|
|
||||||
id: PropTypes.number,
|
|
||||||
color: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
brand: PropTypes.string,
|
|
||||||
isStock: PropTypes.bool,
|
|
||||||
image: PropTypes.string,
|
|
||||||
description: PropTypes.string,
|
|
||||||
offerPrice: PropTypes.number,
|
|
||||||
salePrice: PropTypes.number,
|
|
||||||
offer: PropTypes.string,
|
|
||||||
rating: PropTypes.number
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ProductCard;
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Grid, Rating, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import Avatar from 'components/@extended/Avatar';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { StarFilled, StarOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
const avatarImage = require.context('assets/images/users', true);
|
|
||||||
|
|
||||||
// ==============================|| PRODUCT DETAILS - REVIEW ||============================== //
|
|
||||||
|
|
||||||
const ProductReview = ({ avatar, date, name, rating, review }) => (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" spacing={1}>
|
|
||||||
<Avatar alt={name} src={avatar && avatarImage(`./${avatar}`)} />
|
|
||||||
<Stack spacing={2}>
|
|
||||||
<Stack>
|
|
||||||
<Typography variant="subtitle1" sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', display: 'block' }}>
|
|
||||||
{name}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="caption" color="textSecondary">
|
|
||||||
{date}
|
|
||||||
</Typography>
|
|
||||||
<Rating
|
|
||||||
size="small"
|
|
||||||
name="simple-controlled"
|
|
||||||
value={rating < 4 ? rating + 1 : rating}
|
|
||||||
icon={<StarFilled style={{ fontSize: 'inherit' }} />}
|
|
||||||
emptyIcon={<StarOutlined style={{ fontSize: 'inherit' }} />}
|
|
||||||
precision={0.1}
|
|
||||||
readOnly
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
<Typography variant="body2">{review}</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
|
|
||||||
ProductReview.propTypes = {
|
|
||||||
avatar: PropTypes.string,
|
|
||||||
date: PropTypes.string,
|
|
||||||
name: PropTypes.string,
|
|
||||||
rating: PropTypes.number,
|
|
||||||
review: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ProductReview;
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
// material-ui
|
|
||||||
import { CardContent, Grid, Skeleton, Stack } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
|
|
||||||
// ===========================|| SKELETON - PRODUCT CARD ||=========================== //
|
|
||||||
|
|
||||||
const ProductPlaceholder = () => (
|
|
||||||
<MainCard content={false} boxShadow>
|
|
||||||
<Skeleton variant="rectangular" height={220} />
|
|
||||||
<CardContent sx={{ p: 2 }}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Skeleton variant="rectangular" height={20} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Skeleton variant="rectangular" height={45} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ pt: '8px !important' }}>
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1}>
|
|
||||||
<Skeleton variant="rectangular" height={20} width={90} />
|
|
||||||
<Skeleton variant="rectangular" height={20} width={38} />
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item>
|
|
||||||
<Skeleton variant="rectangular" height={20} width={40} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Skeleton variant="rectangular" height={17} width={20} />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Skeleton variant="rectangular" height={32} width={47} />
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</CardContent>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ProductPlaceholder;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, Chip, Grid, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { FallOutlined, RiseOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| STATISTICS - ECOMMERCE CARD ||============================== //
|
|
||||||
|
|
||||||
const AnalyticEcommerce = ({ color = 'primary', title, count, percentage, isLoss, extra }) => (
|
|
||||||
<MainCard contentSX={{ p: 2.25 }}>
|
|
||||||
<Stack spacing={0.5}>
|
|
||||||
<Typography variant="h6" color="textSecondary">
|
|
||||||
{title}
|
|
||||||
</Typography>
|
|
||||||
<Grid container alignItems="center">
|
|
||||||
<Grid item>
|
|
||||||
<Typography variant="h4" color="inherit">
|
|
||||||
{count}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
{percentage && (
|
|
||||||
<Grid item>
|
|
||||||
<Chip
|
|
||||||
variant="combined"
|
|
||||||
color={color}
|
|
||||||
icon={
|
|
||||||
<>
|
|
||||||
{!isLoss && <RiseOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
|
||||||
{isLoss && <FallOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
label={`${percentage}%`}
|
|
||||||
sx={{ ml: 1.25, pl: 1 }}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</Stack>
|
|
||||||
<Box sx={{ pt: 2.25 }}>
|
|
||||||
<Typography variant="caption" color="textSecondary">
|
|
||||||
You made an extra{' '}
|
|
||||||
<Typography component="span" variant="caption" sx={{ color: `${color || 'primary'}.main` }}>
|
|
||||||
{extra}
|
|
||||||
</Typography>{' '}
|
|
||||||
this year
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
AnalyticEcommerce.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
count: PropTypes.string,
|
|
||||||
percentage: PropTypes.number,
|
|
||||||
isLoss: PropTypes.bool,
|
|
||||||
color: PropTypes.string,
|
|
||||||
extra: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AnalyticEcommerce;
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, Chip, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { RiseOutlined, FallOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| STATISTICS - ECOMMERCE CARD ||============================== //
|
|
||||||
|
|
||||||
const AnalyticsDataCard = ({ color = 'primary', title, count, percentage, isLoss, children }) => (
|
|
||||||
<MainCard content={false}>
|
|
||||||
<Box sx={{ p: 2.25 }}>
|
|
||||||
<Stack spacing={0.5}>
|
|
||||||
<Typography variant="h6" color="textSecondary">
|
|
||||||
{title}
|
|
||||||
</Typography>
|
|
||||||
<Stack direction="row" alignItems="center">
|
|
||||||
<Typography variant="h4" color="inherit">
|
|
||||||
{count}
|
|
||||||
</Typography>
|
|
||||||
{percentage && (
|
|
||||||
<Chip
|
|
||||||
variant="combined"
|
|
||||||
color={color}
|
|
||||||
icon={
|
|
||||||
<>
|
|
||||||
{!isLoss && <RiseOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
|
||||||
{isLoss && <FallOutlined style={{ fontSize: '0.75rem', color: 'inherit' }} />}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
label={`${percentage}%`}
|
|
||||||
sx={{ ml: 1.25, pl: 1 }}
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
{children}
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
AnalyticsDataCard.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
count: PropTypes.string,
|
|
||||||
percentage: PropTypes.number,
|
|
||||||
isLoss: PropTypes.bool,
|
|
||||||
color: PropTypes.string,
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AnalyticsDataCard;
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Chip } from '@mui/material';
|
|
||||||
|
|
||||||
// ==============================|| STATUS CHIP (Doormile-style soft badge) ||============================== //
|
|
||||||
// One consistent soft-filled chip for every lifecycle status across orders,
|
|
||||||
// deliveries, riders, tenants, invoices. Colour encodes meaning; the chip stays
|
|
||||||
// quiet (soft bg + readable dark text) so tables don't turn into a rainbow.
|
|
||||||
|
|
||||||
// Soft background + readable foreground per semantic tone.
|
|
||||||
const TONE = {
|
|
||||||
amber: { bg: '#FEF3C7', fg: '#92400E' },
|
|
||||||
indigo: { bg: '#E0E7FF', fg: '#3730A3' },
|
|
||||||
cyan: { bg: '#CFFAFE', fg: '#155E75' },
|
|
||||||
violet: { bg: '#EDE9FE', fg: '#5B21B6' },
|
|
||||||
teal: { bg: '#CCFBF1', fg: '#115E59' },
|
|
||||||
emerald: { bg: '#D1FAE5', fg: '#065F46' },
|
|
||||||
red: { bg: '#FEE2E2', fg: '#991B1B' },
|
|
||||||
orange: { bg: '#FFEDD5', fg: '#9A3412' },
|
|
||||||
sky: { bg: '#E0F2FE', fg: '#075985' },
|
|
||||||
slate: { bg: '#F1F5F9', fg: '#475569' },
|
|
||||||
brand: { bg: '#F1E6F7', fg: '#5B1F73' }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Status keyword -> tone + display label.
|
|
||||||
const MAP = {
|
|
||||||
pending: { tone: 'amber', label: 'Pending' },
|
|
||||||
created: { tone: 'sky', label: 'Created' },
|
|
||||||
assigned: { tone: 'indigo', label: 'Assigned' },
|
|
||||||
accepted: { tone: 'indigo', label: 'Accepted' },
|
|
||||||
arrived: { tone: 'cyan', label: 'Arrived' },
|
|
||||||
picked: { tone: 'violet', label: 'Picked' },
|
|
||||||
'picked-up':{ tone: 'violet', label: 'Picked Up' },
|
|
||||||
started: { tone: 'cyan', label: 'Started' },
|
|
||||||
active: { tone: 'teal', label: 'Active' },
|
|
||||||
'in-transit': { tone: 'teal', label: 'In Transit' },
|
|
||||||
delivered: { tone: 'emerald', label: 'Delivered' },
|
|
||||||
completed: { tone: 'emerald', label: 'Completed' },
|
|
||||||
skipped: { tone: 'orange', label: 'Skipped' },
|
|
||||||
failed: { tone: 'red', label: 'Failed' },
|
|
||||||
cancelled: { tone: 'red', label: 'Cancelled' },
|
|
||||||
// riders / tenants
|
|
||||||
online: { tone: 'emerald', label: 'Online' },
|
|
||||||
offline: { tone: 'slate', label: 'Offline' },
|
|
||||||
inactive: { tone: 'slate', label: 'Inactive' },
|
|
||||||
idle: { tone: 'amber', label: 'Idle' },
|
|
||||||
unknown: { tone: 'slate', label: 'Unknown' },
|
|
||||||
// invoices
|
|
||||||
paid: { tone: 'emerald', label: 'Paid' },
|
|
||||||
unpaid: { tone: 'amber', label: 'Unpaid' },
|
|
||||||
open: { tone: 'sky', label: 'Open' },
|
|
||||||
overdue: { tone: 'red', label: 'Overdue' },
|
|
||||||
prepaid: { tone: 'emerald', label: 'Prepaid' },
|
|
||||||
cod: { tone: 'amber', label: 'COD' }
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function StatusChip({ status, label, size = 'small', sx }) {
|
|
||||||
const key = String(status || '').toLowerCase().trim().replace(/\s+/g, '-');
|
|
||||||
const cfg = MAP[key] || { tone: 'slate', label: status || '—' };
|
|
||||||
const tone = TONE[cfg.tone] || TONE.slate;
|
|
||||||
return (
|
|
||||||
<Chip
|
|
||||||
size={size}
|
|
||||||
label={label || cfg.label}
|
|
||||||
sx={{ bgcolor: tone.bg, color: tone.fg, border: 'none', fontWeight: 600, ...sx }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusChip.propTypes = {
|
|
||||||
status: PropTypes.string,
|
|
||||||
label: PropTypes.node,
|
|
||||||
size: PropTypes.string,
|
|
||||||
sx: PropTypes.object
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Stack, Typography, Box } from '@mui/material';
|
|
||||||
|
|
||||||
const TitleCard = ({ sx, title, children, starticon }) => {
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
...sx
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack direction="row" flexWrap={'wrap'} alignItems="center" justifyContent="space-between" gap={1}>
|
|
||||||
<Stack>
|
|
||||||
{starticon && starticon}
|
|
||||||
<Typography variant="h3">{title}</Typography>
|
|
||||||
</Stack>
|
|
||||||
{children}
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TitleCard;
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { createContext, useEffect, useReducer } from 'react';
|
|
||||||
|
|
||||||
// third-party
|
|
||||||
import { Chance } from 'chance';
|
|
||||||
import jwtDecode from 'jwt-decode';
|
|
||||||
|
|
||||||
// reducer - state management
|
|
||||||
import { LOGIN, LOGOUT } from 'store/reducers/actions';
|
|
||||||
import authReducer from 'store/reducers/auth';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import Loader from 'components/Loader';
|
|
||||||
import axios from 'utils/axios';
|
|
||||||
|
|
||||||
const chance = new Chance();
|
|
||||||
|
|
||||||
// constant
|
|
||||||
const initialState = {
|
|
||||||
isLoggedIn: false,
|
|
||||||
isInitialized: false,
|
|
||||||
user: null
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const verifyToken = (serviceToken) => {
|
|
||||||
if (!serviceToken) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const decoded = jwtDecode(serviceToken);
|
|
||||||
/**
|
|
||||||
* Property 'exp' does not exist on type '<T = unknown>(token: string, options?: JwtDecodeOptions | undefined) => T'.
|
|
||||||
*/
|
|
||||||
return decoded.exp > Date.now() / 1000;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setSession = (serviceToken) => {
|
|
||||||
if (serviceToken) {
|
|
||||||
localStorage.setItem('serviceToken', serviceToken);
|
|
||||||
axios.defaults.headers.common.Authorization = `Bearer ${serviceToken}`;
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem('serviceToken');
|
|
||||||
delete axios.defaults.headers.common.Authorization;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// ==============================|| JWT CONTEXT & PROVIDER ||============================== //
|
|
||||||
|
|
||||||
const JWTContext = createContext(null);
|
|
||||||
|
|
||||||
export const JWTProvider = ({ children }) => {
|
|
||||||
const [state, dispatch] = useReducer(authReducer, initialState);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const init = async () => {
|
|
||||||
console.log(verifyToken)
|
|
||||||
// try {
|
|
||||||
// const serviceToken = window.localStorage.getItem('serviceToken');
|
|
||||||
// if (serviceToken && verifyToken(serviceToken)) {
|
|
||||||
// setSession(serviceToken);
|
|
||||||
// const response = await axios.get('/api/account/me');
|
|
||||||
// const { user } = response.data;
|
|
||||||
// dispatch({
|
|
||||||
// type: LOGIN,
|
|
||||||
// payload: {
|
|
||||||
// isLoggedIn: true,
|
|
||||||
// user
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// dispatch({
|
|
||||||
// type: LOGOUT
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// } catch (err) {
|
|
||||||
// console.error(err);
|
|
||||||
// dispatch({
|
|
||||||
// type: LOGOUT
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
|
||||||
|
|
||||||
init();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const login = async (email, password) => {
|
|
||||||
const response = await axios.post('/api/account/login', { email, password });
|
|
||||||
const { serviceToken, user } = response.data;
|
|
||||||
setSession(serviceToken);
|
|
||||||
dispatch({
|
|
||||||
type: LOGIN,
|
|
||||||
payload: {
|
|
||||||
isLoggedIn: true,
|
|
||||||
user
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const register = async (email, password, firstName, lastName) => {
|
|
||||||
// todo: this flow need to be recode as it not verified
|
|
||||||
const id = chance.bb_pin();
|
|
||||||
const response = await axios.post('/api/account/register', {
|
|
||||||
id,
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
firstName,
|
|
||||||
lastName
|
|
||||||
});
|
|
||||||
let users = response.data;
|
|
||||||
|
|
||||||
if (window.localStorage.getItem('users') !== undefined && window.localStorage.getItem('users') !== null) {
|
|
||||||
const localUsers = window.localStorage.getItem('users');
|
|
||||||
users = [
|
|
||||||
...JSON.parse(localUsers),
|
|
||||||
{
|
|
||||||
id,
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
name: `${firstName} ${lastName}`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
window.localStorage.setItem('users', JSON.stringify(users));
|
|
||||||
};
|
|
||||||
|
|
||||||
const logout = () => {
|
|
||||||
setSession(null);
|
|
||||||
dispatch({ type: LOGOUT });
|
|
||||||
};
|
|
||||||
|
|
||||||
const resetPassword = async () => {};
|
|
||||||
|
|
||||||
const updateProfile = () => {};
|
|
||||||
|
|
||||||
if (state.isInitialized !== undefined && !state.isInitialized) {
|
|
||||||
return <Loader />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <JWTContext.Provider value={{ ...state, login, logout, register, resetPassword, updateProfile }}>{children}</JWTContext.Provider>;
|
|
||||||
};
|
|
||||||
|
|
||||||
JWTProvider.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default JWTContext;
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { useContext } from 'react';
|
|
||||||
|
|
||||||
// auth provider
|
|
||||||
import AuthContext from 'contexts/JWTContext';
|
|
||||||
|
|
||||||
// ==============================|| AUTH HOOKS ||============================== //
|
|
||||||
|
|
||||||
const useAuth = () => {
|
|
||||||
const context = useContext(AuthContext);
|
|
||||||
|
|
||||||
if (!context) throw new Error('context must be use inside provider');
|
|
||||||
|
|
||||||
return context;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useAuth;
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
// ==============================|| CARD - PAGINATION ||============================== //
|
|
||||||
|
|
||||||
export default function usePagination(data, itemsPerPage) {
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
|
||||||
const maxPage = Math.ceil(data.length / itemsPerPage);
|
|
||||||
|
|
||||||
function currentData() {
|
|
||||||
const begin = (currentPage - 1) * itemsPerPage;
|
|
||||||
const end = begin + itemsPerPage;
|
|
||||||
return data.slice(begin, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
function next() {
|
|
||||||
setCurrentPage((currentPage) => Math.min(currentPage + 1, maxPage));
|
|
||||||
}
|
|
||||||
|
|
||||||
function prev() {
|
|
||||||
setCurrentPage((currentPage) => Math.max(currentPage - 1, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
function jump(page) {
|
|
||||||
const pageNumber = Math.max(1, page);
|
|
||||||
setCurrentPage(() => Math.min(pageNumber, maxPage));
|
|
||||||
}
|
|
||||||
|
|
||||||
return { next, prev, jump, currentData, currentPage, maxPage };
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
// ==============================|| ELEMENT REFERENCE HOOKS ||============================== //
|
|
||||||
|
|
||||||
const useScriptRef = () => {
|
|
||||||
const scripted = useRef(true);
|
|
||||||
|
|
||||||
useEffect(
|
|
||||||
() => () => {
|
|
||||||
scripted.current = false;
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return scripted;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useScriptRef;
|
|
||||||
@@ -27,7 +27,7 @@ import Transitions from 'components/@extended/Transitions';
|
|||||||
import useConfig from 'hooks/useConfig';
|
import useConfig from 'hooks/useConfig';
|
||||||
import { dispatch, useSelector } from 'store';
|
import { dispatch, useSelector } from 'store';
|
||||||
import { activeItem } from 'store/reducers/menu';
|
import { activeItem } from 'store/reducers/menu';
|
||||||
import { MenuOrientation, ThemeMode } from 'config';
|
import { MenuOrientation } from 'config';
|
||||||
|
|
||||||
// assets
|
// assets
|
||||||
import { BorderOutlined, DownOutlined, UpOutlined, RightOutlined } from '@ant-design/icons';
|
import { BorderOutlined, DownOutlined, UpOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { forwardRef, useEffect } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { useMediaQuery, Avatar, Chip, ListItemButton, ListItemText, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import { ThemeMode } from 'config';
|
|
||||||
import { dispatch, useSelector } from 'store';
|
|
||||||
import { activeComponent, openComponentDrawer } from 'store/reducers/menu';
|
|
||||||
|
|
||||||
// ==============================|| NAVIGATION - LIST ITEM ||============================== //
|
|
||||||
|
|
||||||
const NavItem = ({ item }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const matchesMD = useMediaQuery(theme.breakpoints.down('md'));
|
|
||||||
|
|
||||||
const menu = useSelector((state) => state.menu);
|
|
||||||
const { openComponent } = menu;
|
|
||||||
|
|
||||||
let itemTarget = '_self';
|
|
||||||
if (item.target) {
|
|
||||||
itemTarget = '_blank';
|
|
||||||
}
|
|
||||||
|
|
||||||
let listItemProps = { component: forwardRef((props, ref) => <Link {...props} to={item.url} target={itemTarget} ref={ref} />) };
|
|
||||||
if (item?.external) {
|
|
||||||
listItemProps = { component: 'a', href: item.url, target: itemTarget };
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemHandler = (id) => {
|
|
||||||
dispatch(activeComponent({ openComponent: id }));
|
|
||||||
if (matchesMD) dispatch(openComponentDrawer({ componentDrawerOpen: false }));
|
|
||||||
};
|
|
||||||
|
|
||||||
// active menu item on page load
|
|
||||||
useEffect(() => {
|
|
||||||
const currentIndex = document.location.pathname
|
|
||||||
.toString()
|
|
||||||
.split('/')
|
|
||||||
.findIndex((id) => id === item.id);
|
|
||||||
if (currentIndex > -1) {
|
|
||||||
dispatch(activeComponent({ openComponent: item.id }));
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const textColor = theme.palette.mode === ThemeMode.DARK ? 'grey.400' : 'text.primary';
|
|
||||||
const iconSelectedColor = theme.palette.mode === ThemeMode.DARK ? 'text.primary' : 'primary.main';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ListItemButton
|
|
||||||
{...listItemProps}
|
|
||||||
disabled={item.disabled}
|
|
||||||
onClick={() => itemHandler(item.id)}
|
|
||||||
selected={openComponent === item.id}
|
|
||||||
sx={{
|
|
||||||
pl: 4,
|
|
||||||
py: 1,
|
|
||||||
mb: 0.5,
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
|
||||||
},
|
|
||||||
'&.Mui-selected': {
|
|
||||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
|
|
||||||
borderRight: `2px solid ${theme.palette.primary.main}`,
|
|
||||||
'&:hover': {
|
|
||||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemText
|
|
||||||
primary={
|
|
||||||
<Typography variant="h6" sx={{ color: openComponent === item.id ? iconSelectedColor : textColor }}>
|
|
||||||
{item.title}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{item.chip && (
|
|
||||||
<Chip
|
|
||||||
color={item.chip.color}
|
|
||||||
variant={item.chip.variant}
|
|
||||||
size={item.chip.size}
|
|
||||||
label={item.chip.label}
|
|
||||||
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</ListItemButton>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
NavItem.propTypes = {
|
|
||||||
item: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NavItem;
|
|
||||||
@@ -13,9 +13,6 @@ import useConfig from 'hooks/useConfig';
|
|||||||
import logo from 'assets/images/doormile-logo.png'
|
import logo from 'assets/images/doormile-logo.png'
|
||||||
import logo1 from 'assets/images/doormile-mark.png'
|
import logo1 from 'assets/images/doormile-mark.png'
|
||||||
|
|
||||||
// doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for the light sidebar background.
|
|
||||||
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(14%) sepia(85%) saturate(4649%) hue-rotate(345deg) brightness(97%) contrast(92%)';
|
|
||||||
|
|
||||||
// ==============================|| DRAWER HEADER ||============================== //
|
// ==============================|| DRAWER HEADER ||============================== //
|
||||||
|
|
||||||
const DrawerHeader = ({ open }) => {
|
const DrawerHeader = ({ open }) => {
|
||||||
@@ -37,8 +34,6 @@ const DrawerHeader = ({ open }) => {
|
|||||||
paddingLeft: isHorizontal ? { xs: '24px', lg: '0' } : open ? '24px' : 0
|
paddingLeft: isHorizontal ? { xs: '24px', lg: '0' } : open ? '24px' : 0
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <Logo isIcon={!open} sx={{ width: open ? 'auto' : 35, height: 35 }} /> */}
|
|
||||||
|
|
||||||
{(open) &&
|
{(open) &&
|
||||||
<img src={logo}
|
<img src={logo}
|
||||||
style={{ height: '29px', width: 'auto' }}
|
style={{ height: '29px', width: 'auto' }}
|
||||||
|
|||||||
@@ -106,24 +106,6 @@ const soft = (c) => a(c, '18');
|
|||||||
const ring = (c) => a(c, '26');
|
const ring = (c) => a(c, '26');
|
||||||
const edge = (c) => a(c, '55');
|
const edge = (c) => a(c, '55');
|
||||||
|
|
||||||
const pillFieldSx = (color) => ({
|
|
||||||
cursor: 'pointer',
|
|
||||||
'& .MuiOutlinedInput-root': {
|
|
||||||
borderRadius: '10px',
|
|
||||||
bgcolor: '#ffffff',
|
|
||||||
fontWeight: 600,
|
|
||||||
color: DT.textPrimary,
|
|
||||||
paddingRight: '8px',
|
|
||||||
cursor: 'pointer',
|
|
||||||
transition: 'border-color 0.15s, box-shadow 0.15s, background-color 0.2s',
|
|
||||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
|
||||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
|
||||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` },
|
|
||||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
|
|
||||||
},
|
|
||||||
'& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: color }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Status palette — drives the pill tabs and per-row badges.
|
// Status palette — drives the pill tabs and per-row badges.
|
||||||
const STATUS_META = {
|
const STATUS_META = {
|
||||||
active: { label: 'Active', color: '#10b981', icon: MdCheckCircle, statusKey: 'active' },
|
active: { label: 'Active', color: '#10b981', icon: MdCheckCircle, statusKey: 'active' },
|
||||||
@@ -202,7 +184,7 @@ const Clients1 = () => {
|
|||||||
const [latlong, setLatlong] = useState({});
|
const [latlong, setLatlong] = useState({});
|
||||||
const [editClient, setEditClient] = useState({});
|
const [editClient, setEditClient] = useState({});
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [tabStatus, setTabStatus] = useState('Active');
|
const [, setTabStatus] = useState('Active');
|
||||||
|
|
||||||
const handleChangePage = (event, newPage) => {
|
const handleChangePage = (event, newPage) => {
|
||||||
setPage(newPage);
|
setPage(newPage);
|
||||||
@@ -1785,14 +1767,6 @@ const Clients1 = () => {
|
|||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={latlong.lng}
|
value={latlong.lng}
|
||||||
// onChange={(e) => {
|
|
||||||
// setLongi(e.target.value.toString())
|
|
||||||
// setEditClient({
|
|
||||||
// ...editClient,
|
|
||||||
// longitude:
|
|
||||||
// e.target.value.toString(),
|
|
||||||
// });
|
|
||||||
// }}
|
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
|
|
||||||
// material-ui
|
// material-ui
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import { Box, Button, FormLabel, Grid, InputLabel, MenuItem, Select, Stack, TextField, Typography, useMediaQuery } from '@mui/material';
|
import { Button, Grid, InputLabel, MenuItem, Select, Stack, TextField, Typography, useMediaQuery } from '@mui/material';
|
||||||
|
|
||||||
// third-party
|
// third-party
|
||||||
// import { PatternFormat } from 'react-number-format';
|
// import { PatternFormat } from 'react-number-format';
|
||||||
@@ -55,8 +55,6 @@ const Createclient = () => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// fetchprofiledetails(localStorage.getItem('appuserid'));
|
|
||||||
// fetchprofiledetails(181);
|
|
||||||
if (localStorage.getItem('tenantid')) {
|
if (localStorage.getItem('tenantid')) {
|
||||||
fetchtenantinfo(localStorage.getItem('tenantid'));
|
fetchtenantinfo(localStorage.getItem('tenantid'));
|
||||||
}
|
}
|
||||||
@@ -93,41 +91,6 @@ const Createclient = () => {
|
|||||||
// console.log(alertmessage)
|
// console.log(alertmessage)
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchprofiledetails = async (userid) => {
|
|
||||||
if (userid) {
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
await axios
|
|
||||||
.get(`${process.env.REACT_APP_URL2}/tenants/getclient?id=${userid}`)
|
|
||||||
.then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
if (res.data.message === 'Successful') {
|
|
||||||
let res1 = res.data.details;
|
|
||||||
setMobilenumber(res1.contactno);
|
|
||||||
setEmailaddress(res1.primaryemail);
|
|
||||||
setAddress(res1.address);
|
|
||||||
setCity(res1.city);
|
|
||||||
setZipcode(res1.postcode);
|
|
||||||
setState(res1.state);
|
|
||||||
setSuburb(res1.suburb);
|
|
||||||
setLatlong({
|
|
||||||
lat: res1.latitude,
|
|
||||||
lng: res1.longitude
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchtenantinfo = async (tid) => {
|
const fetchtenantinfo = async (tid) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await axios
|
await axios
|
||||||
@@ -256,10 +219,6 @@ const Createclient = () => {
|
|||||||
autoHideDuration: 2000
|
autoHideDuration: 2000
|
||||||
});
|
});
|
||||||
navigate('/clients');
|
navigate('/clients');
|
||||||
// setTimeout(()=>{
|
|
||||||
// fetchprofiledetails(localStorage.getItem('appuserid'));
|
|
||||||
|
|
||||||
// },2000)
|
|
||||||
} else if (res.data.message == 'Customer Already available') {
|
} else if (res.data.message == 'Customer Already available') {
|
||||||
enqueueSnackbar('Customer Already available', {
|
enqueueSnackbar('Customer Already available', {
|
||||||
variant: 'error',
|
variant: 'error',
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ import {
|
|||||||
MdLocationOn,
|
MdLocationOn,
|
||||||
MdEdit,
|
MdEdit,
|
||||||
MdGroups,
|
MdGroups,
|
||||||
MdHowToReg,
|
|
||||||
MdPlace,
|
|
||||||
MdOutlineGroups,
|
MdOutlineGroups,
|
||||||
MdOutlineHowToReg,
|
MdOutlineHowToReg,
|
||||||
MdOutlinePlace
|
MdOutlinePlace
|
||||||
@@ -273,14 +271,6 @@ export default function Customers() {
|
|||||||
}
|
}
|
||||||
}, [address]);
|
}, [address]);
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// selectedCustomer &&
|
|
||||||
// setLatlong({
|
|
||||||
// lat: selectedCustomer.latitude,
|
|
||||||
// lng: selectedCustomer.longitude
|
|
||||||
// });
|
|
||||||
// }, [selectedCustomer]);
|
|
||||||
|
|
||||||
// ==============================|| getallcustomers (customers) ||============================== //
|
// ==============================|| getallcustomers (customers) ||============================== //
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {
|
|||||||
MdStorefront,
|
MdStorefront,
|
||||||
MdLocationOn,
|
MdLocationOn,
|
||||||
MdDirectionsBike,
|
MdDirectionsBike,
|
||||||
MdLocalShipping,
|
|
||||||
MdNotificationsActive,
|
MdNotificationsActive,
|
||||||
MdPersonPin,
|
MdPersonPin,
|
||||||
MdHistoryToggleOff,
|
MdHistoryToggleOff,
|
||||||
@@ -325,7 +324,6 @@ const Deliveries = () => {
|
|||||||
const [tabstatus, setTabstatus] = useState('Pending');
|
const [tabstatus, setTabstatus] = useState('Pending');
|
||||||
const [tabvalue, setTabvalue] = useState(0);
|
const [tabvalue, setTabvalue] = useState(0);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [datestatus, setDatestatus] = useState('Today');
|
|
||||||
const [kms, setKms] = useState('');
|
const [kms, setKms] = useState('');
|
||||||
const [cumulativekms, setCumulativeKms] = useState();
|
const [cumulativekms, setCumulativeKms] = useState();
|
||||||
const [deliveryamount, setDeliveryamount] = useState();
|
const [deliveryamount, setDeliveryamount] = useState();
|
||||||
@@ -339,7 +337,6 @@ const Deliveries = () => {
|
|||||||
const tenantRef = useRef(null);
|
const tenantRef = useRef(null);
|
||||||
const [page, setPage] = React.useState(0);
|
const [page, setPage] = React.useState(0);
|
||||||
const [rowsPerPage, setRowsPerPage] = React.useState(50);
|
const [rowsPerPage, setRowsPerPage] = React.useState(50);
|
||||||
const [totalCount, setTotalCount] = React.useState();
|
|
||||||
const [productCollapse, setProductCollapse] = useState(null);
|
const [productCollapse, setProductCollapse] = useState(null);
|
||||||
const [orderHeaderid, setOrderHeaderId] = useState(null);
|
const [orderHeaderid, setOrderHeaderId] = useState(null);
|
||||||
const [searchword, setSearchword] = useState('');
|
const [searchword, setSearchword] = useState('');
|
||||||
@@ -347,8 +344,6 @@ const Deliveries = () => {
|
|||||||
const [menuAnchorEl, setMenuAnchorEl] = React.useState(null);
|
const [menuAnchorEl, setMenuAnchorEl] = React.useState(null);
|
||||||
const [selectedRow, setSelectedRow] = useState(null);
|
const [selectedRow, setSelectedRow] = useState(null);
|
||||||
const [loading1, setLoading1] = useState(false);
|
const [loading1, setLoading1] = useState(false);
|
||||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
||||||
const [open2, setOpen2] = useState('');
|
|
||||||
const [cancelDeliveryOpen, setCancelDeliveryOpen] = useState(false);
|
const [cancelDeliveryOpen, setCancelDeliveryOpen] = useState(false);
|
||||||
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
|
const [changeDialogOpen, setChangeDialogOpen] = useState(false);
|
||||||
const [cancelFeed, setCancelFeed] = useState('');
|
const [cancelFeed, setCancelFeed] = useState('');
|
||||||
@@ -488,7 +483,7 @@ const Deliveries = () => {
|
|||||||
countSourceRefetch(); // Refresh the all-statuses dataset feeding table + chips
|
countSourceRefetch(); // Refresh the all-statuses dataset feeding table + chips
|
||||||
notifyRiderMutation.mutate(selectedRider.userfcmtoken);
|
notifyRiderMutation.mutate(selectedRider.userfcmtoken);
|
||||||
},
|
},
|
||||||
onError: (err, { selectedRider, selectedRow }) => {
|
onError: (err, { selectedRow }) => {
|
||||||
logger.error(`Failed to change rider for order ID ${selectedRow?.orderid}:`, err);
|
logger.error(`Failed to change rider for order ID ${selectedRow?.orderid}:`, err);
|
||||||
opentoast(err.message, 'error');
|
opentoast(err.message, 'error');
|
||||||
setLoading1(false);
|
setLoading1(false);
|
||||||
@@ -524,43 +519,35 @@ const Deliveries = () => {
|
|||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
setTabstatus('Pending');
|
setTabstatus('Pending');
|
||||||
setCurrentStatus('pending');
|
setCurrentStatus('pending');
|
||||||
setTotalCount(countData?.uncoveredLength);
|
|
||||||
}
|
}
|
||||||
if (i === 1) {
|
if (i === 1) {
|
||||||
setTabstatus('Assigned');
|
setTabstatus('Assigned');
|
||||||
setCurrentStatus('accepted');
|
setCurrentStatus('accepted');
|
||||||
setTotalCount(countData?.assignedLength);
|
|
||||||
}
|
}
|
||||||
if (i === 2) {
|
if (i === 2) {
|
||||||
setTabstatus('Arrived');
|
setTabstatus('Arrived');
|
||||||
setCurrentStatus('arrived');
|
setCurrentStatus('arrived');
|
||||||
setTotalCount(countData?.arrivedLength);
|
|
||||||
}
|
}
|
||||||
if (i === 3) {
|
if (i === 3) {
|
||||||
setTabstatus('Picked');
|
setTabstatus('Picked');
|
||||||
setCurrentStatus('picked');
|
setCurrentStatus('picked');
|
||||||
setTotalCount(countData?.pickedLength);
|
|
||||||
}
|
}
|
||||||
if (i === 4) {
|
if (i === 4) {
|
||||||
setTabstatus('Active');
|
setTabstatus('Active');
|
||||||
setCurrentStatus('active');
|
setCurrentStatus('active');
|
||||||
setTotalCount(countData?.activeLength);
|
|
||||||
}
|
}
|
||||||
if (i === 5) {
|
if (i === 5) {
|
||||||
setTabstatus('Skipped');
|
setTabstatus('Skipped');
|
||||||
setCurrentStatus('skipped');
|
setCurrentStatus('skipped');
|
||||||
setTotalCount(countData?.skippedLength);
|
|
||||||
}
|
}
|
||||||
if (i === 6) {
|
if (i === 6) {
|
||||||
setTabstatus('Delivered');
|
setTabstatus('Delivered');
|
||||||
setCurrentStatus('delivered');
|
setCurrentStatus('delivered');
|
||||||
setTotalCount(countData?.coveredLength);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i === 7) {
|
if (i === 7) {
|
||||||
setTabstatus('Cancelled');
|
setTabstatus('Cancelled');
|
||||||
setCurrentStatus('cancelled');
|
setCurrentStatus('cancelled');
|
||||||
setTotalCount(countData?.cancelLength);
|
|
||||||
}
|
}
|
||||||
console.log(i);
|
console.log(i);
|
||||||
setSearchword('');
|
setSearchword('');
|
||||||
@@ -807,13 +794,6 @@ const Deliveries = () => {
|
|||||||
queryKey: ['fetchCountData', appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid, tabstatus],
|
queryKey: ['fetchCountData', appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid, tabstatus],
|
||||||
queryFn: () => fetchCountAPI(appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid)
|
queryFn: () => fetchCountAPI(appId, userid, startdate, enddate, rowsPerPage, debouncedSearch, tenantid, locationid, riderid)
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
|
||||||
console.log('countData', countData);
|
|
||||||
if (tabvalue === 0 && countData) {
|
|
||||||
setTotalCount(countData.uncoveredLength);
|
|
||||||
}
|
|
||||||
}, [countData]);
|
|
||||||
|
|
||||||
// ==============================|| fetchRidersList ||============================== //
|
// ==============================|| fetchRidersList ||============================== //
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -2597,11 +2577,6 @@ const Deliveries = () => {
|
|||||||
} else {
|
} else {
|
||||||
setStartdate(dayjs(range.startDate).format('YYYY-MM-DD'));
|
setStartdate(dayjs(range.startDate).format('YYYY-MM-DD'));
|
||||||
setEnddate(dayjs(range.endDate).format('YYYY-MM-DD'));
|
setEnddate(dayjs(range.endDate).format('YYYY-MM-DD'));
|
||||||
if (range.label) {
|
|
||||||
setDatestatus(range.label);
|
|
||||||
} else {
|
|
||||||
setDatestatus('');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
console.log(range);
|
console.log(range);
|
||||||
}}
|
}}
|
||||||
@@ -2646,11 +2621,6 @@ const Deliveries = () => {
|
|||||||
startDate: startOfMonth(addMonths(new Date(), -1)),
|
startDate: startOfMonth(addMonths(new Date(), -1)),
|
||||||
endDate: endOfMonth(addMonths(new Date(), -1))
|
endDate: endOfMonth(addMonths(new Date(), -1))
|
||||||
}
|
}
|
||||||
// {
|
|
||||||
// label: 'All',
|
|
||||||
// startDate: new Date(),
|
|
||||||
// endDate: addDays(new Date(), -1),
|
|
||||||
// },
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ const ActiveSection = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderActiveDeliveryCard = (o, i) => {
|
const renderActiveDeliveryCard = (o) => {
|
||||||
const rid = o.rider_id || o.userid;
|
const rid = o.rider_id || o.userid;
|
||||||
const rider = riders.find((r) => String(r.id) === String(rid));
|
const rider = riders.find((r) => String(r.id) === String(rid));
|
||||||
const color = getRiderColor(rid);
|
const color = getRiderColor(rid);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
||||||
import { MapContainer, TileLayer, Marker, Popup, Polyline, Tooltip, useMap, useMapEvents, ZoomControl } from 'react-leaflet';
|
import { MapContainer, TileLayer, Marker, Popup, Polyline, Tooltip, useMap, ZoomControl } from 'react-leaflet';
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
// Side-effect import: patches L.Polyline so pathOptions.offset (in screen px)
|
// Side-effect import: patches L.Polyline so pathOptions.offset (in screen px)
|
||||||
@@ -22,7 +22,6 @@ import {
|
|||||||
MdStraighten,
|
MdStraighten,
|
||||||
MdLocationOn,
|
MdLocationOn,
|
||||||
MdMarkunreadMailbox,
|
MdMarkunreadMailbox,
|
||||||
MdMoveToInbox,
|
|
||||||
MdPlace,
|
MdPlace,
|
||||||
MdTwoWheeler,
|
MdTwoWheeler,
|
||||||
MdNotes,
|
MdNotes,
|
||||||
@@ -59,7 +58,6 @@ import ProfitabilitySection from './ProfitabilitySection';
|
|||||||
import ActiveSection from './ActiveSection';
|
import ActiveSection from './ActiveSection';
|
||||||
import { fetchDeliveries, fetchAppLocations, getRiderPeriodicLogs, fetchRidersLogs, fetchBatchEfficiency } from '../../api/api';
|
import { fetchDeliveries, fetchAppLocations, getRiderPeriodicLogs, fetchRidersLogs, fetchBatchEfficiency } from '../../api/api';
|
||||||
import {
|
import {
|
||||||
STATUS_STYLES,
|
|
||||||
getStatusStyle,
|
getStatusStyle,
|
||||||
FINAL_STATUSES,
|
FINAL_STATUSES,
|
||||||
SKIPPED_STATUSES,
|
SKIPPED_STATUSES,
|
||||||
@@ -232,15 +230,6 @@ const getRowBatch = (r, fieldId = 'all', batches = BATCHES_DEFAULT) => {
|
|||||||
return getBatchForHour(d.hour() + d.minute() / 60, batches);
|
return getBatchForHour(d.hour() + d.minute() / 60, batches);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sits inside the Compare MapContainer and unpins any pinned popup whenever
|
|
||||||
// the operator clicks empty map space. Markers' click events do NOT bubble
|
|
||||||
// to the map, so this only fires on background clicks (which is what we
|
|
||||||
// want — clicking elsewhere should release the pin).
|
|
||||||
function CompareMapClickUnpin({ onUnpin }) {
|
|
||||||
useMapEvents({ click: () => onUnpin() });
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Captures the Leaflet map instance for the parent component via a ref. Kept
|
// Captures the Leaflet map instance for the parent component via a ref. Kept
|
||||||
// available even after the two-map Compare layout was unified into one map,
|
// available even after the two-map Compare layout was unified into one map,
|
||||||
// since future per-step imperative zoom logic still needs a handle on the
|
// since future per-step imperative zoom logic still needs a handle on the
|
||||||
@@ -983,12 +972,6 @@ const ANALYSIS_BATCH_WINDOWS = [
|
|||||||
|
|
||||||
// Tolerant field-name lookup so the Analysis card still renders cleanly even
|
// Tolerant field-name lookup so the Analysis card still renders cleanly even
|
||||||
// if the API response uses slightly different keys than expected.
|
// if the API response uses slightly different keys than expected.
|
||||||
const analysisPick = (obj, keys) => {
|
|
||||||
for (const k of keys) {
|
|
||||||
if (obj && obj[k] != null && obj[k] !== '') return obj[k];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
const analysisFormatNum = (v) => {
|
const analysisFormatNum = (v) => {
|
||||||
if (v == null) return '—';
|
if (v == null) return '—';
|
||||||
if (typeof v === 'number') return v.toLocaleString('en-IN');
|
if (typeof v === 'number') return v.toLocaleString('en-IN');
|
||||||
@@ -996,14 +979,6 @@ const analysisFormatNum = (v) => {
|
|||||||
if (Number.isFinite(n)) return n.toLocaleString('en-IN');
|
if (Number.isFinite(n)) return n.toLocaleString('en-IN');
|
||||||
return String(v);
|
return String(v);
|
||||||
};
|
};
|
||||||
const analysisFormatKm = (v) => (v == null ? '—' : `${parseFloat(v).toFixed(1)} km`);
|
|
||||||
const analysisFormatRupees = (v) => (v == null ? '—' : `₹${parseFloat(v).toFixed(0)}`);
|
|
||||||
const analysisFormatPct = (v) => {
|
|
||||||
if (v == null) return '—';
|
|
||||||
const n = parseFloat(v);
|
|
||||||
if (!Number.isFinite(n)) return '—';
|
|
||||||
return `${n > 1 ? n.toFixed(1) : (n * 100).toFixed(1)}%`;
|
|
||||||
};
|
|
||||||
// Parse "HH:mm:ss" or "HH:mm" → seconds since midnight. Returns null when the
|
// Parse "HH:mm:ss" or "HH:mm" → seconds since midnight. Returns null when the
|
||||||
// string is missing or malformed. Used to compute gantt percentages for the
|
// string is missing or malformed. Used to compute gantt percentages for the
|
||||||
// rider timelines on the Analysis page — the API ships those fields as bare
|
// rider timelines on the Analysis page — the API ships those fields as bare
|
||||||
@@ -1163,7 +1138,6 @@ const Dispatch = ({
|
|||||||
// Short-lived close timer for the general map order/marker popups.
|
// Short-lived close timer for the general map order/marker popups.
|
||||||
// Gives the cursor a ~200ms window to travel from the marker onto the popup
|
// Gives the cursor a ~200ms window to travel from the marker onto the popup
|
||||||
// or vice versa without immediately triggering a close.
|
// or vice versa without immediately triggering a close.
|
||||||
const activePopupMarkerRef = useRef(null);
|
|
||||||
const popupHoverTimerRef = useRef(null);
|
const popupHoverTimerRef = useRef(null);
|
||||||
// Order shown in the centered popup overlay. Rendered outside the leaflet
|
// Order shown in the centered popup overlay. Rendered outside the leaflet
|
||||||
// map (see `dispatch-popup-center` overlay near the bottom of the JSX) so
|
// map (see `dispatch-popup-center` overlay near the bottom of the JSX) so
|
||||||
@@ -3150,7 +3124,7 @@ const Dispatch = ({
|
|||||||
? new Map(riderActualTracks.map((t) => [String(t.deliveryid), t.sequenceStep]))
|
? new Map(riderActualTracks.map((t) => [String(t.deliveryid), t.sequenceStep]))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return ordersToRender.map((o, idx) => {
|
return ordersToRender.map((o) => {
|
||||||
const rid = o.rider_id;
|
const rid = o.rider_id;
|
||||||
const active = rid ? activeRiders.has(rid) : true;
|
const active = rid ? activeRiders.has(rid) : true;
|
||||||
let color = getRiderColor(rid);
|
let color = getRiderColor(rid);
|
||||||
@@ -3477,13 +3451,6 @@ const Dispatch = ({
|
|||||||
return routes;
|
return routes;
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleRider = (rid) => {
|
|
||||||
const newActive = new Set(activeRiders);
|
|
||||||
if (newActive.has(rid)) newActive.delete(rid);
|
|
||||||
else newActive.add(rid);
|
|
||||||
setActiveRiders(newActive);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`dispatch-container${embedded ? ' embedded' : ''}${compareOpen ? ' compare-open' : ''}`}>
|
<div className={`dispatch-container${embedded ? ' embedded' : ''}${compareOpen ? ' compare-open' : ''}`}>
|
||||||
{!embedded && (
|
{!embedded && (
|
||||||
@@ -5373,15 +5340,6 @@ const Dispatch = ({
|
|||||||
(o) => o.deliveryid != null && String(o.deliveryid) === String(t.deliveryid)
|
(o) => o.deliveryid != null && String(o.deliveryid) === String(t.deliveryid)
|
||||||
);
|
);
|
||||||
|
|
||||||
const statusStyle = getStatusStyle(t.orderstatus);
|
|
||||||
const flagSvg = t.orderstatus
|
|
||||||
? `<svg class="cmark-flag" viewBox="0 0 18 22" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<line x1="1.5" y1="0" x2="1.5" y2="22" stroke="#0f172a" stroke-width="1.6" stroke-linecap="round"/>
|
|
||||||
<polygon points="2,1 17,1 13.5,5.5 17,10 2,10" fill="${statusStyle.bg}" stroke="#0f172a" stroke-width="0.6" stroke-linejoin="round"/>
|
|
||||||
${isDelivered ? '<polyline points="5,5.5 7,7.5 11,3.5" fill="none" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>' : ''}
|
|
||||||
</svg>`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const dropClasses = ['compare-step-pin'];
|
const dropClasses = ['compare-step-pin'];
|
||||||
if (isFocusedStep) dropClasses.push('is-focused');
|
if (isFocusedStep) dropClasses.push('is-focused');
|
||||||
if (isDelivered) dropClasses.push('is-delivered');
|
if (isDelivered) dropClasses.push('is-delivered');
|
||||||
|
|||||||
@@ -9,12 +9,9 @@ import logo_nearle1 from '../../../assets/images/doormile-logo.png';
|
|||||||
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)';
|
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import Loader from 'components/Loader';
|
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import { DownloadOutlined, PrinterFilled } from '@ant-design/icons';
|
import { PrinterFilled } from '@ant-design/icons';
|
||||||
import ReactToPrint, { useReactToPrint } from 'react-to-print';
|
import ReactToPrint from 'react-to-print';
|
||||||
import { SearchOutlined, LeftOutlined, RightOutlined } from '@ant-design/icons';
|
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
|
||||||
// import jsPDF from 'jspdf';
|
// import jsPDF from 'jspdf';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { FaArrowLeft } from 'react-icons/fa6';
|
import { FaArrowLeft } from 'react-icons/fa6';
|
||||||
@@ -30,14 +27,9 @@ import {
|
|||||||
TableCell,
|
TableCell,
|
||||||
TableContainer,
|
TableContainer,
|
||||||
TableHead,
|
TableHead,
|
||||||
TablePagination,
|
|
||||||
TableRow,
|
TableRow,
|
||||||
Tabs,
|
|
||||||
Tab,
|
|
||||||
Typography,
|
Typography,
|
||||||
Box,
|
Box,
|
||||||
OutlinedInput,
|
|
||||||
InputAdornment,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
TextField,
|
TextField,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@@ -55,7 +47,6 @@ const InvoicePreview = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
console.log('previewSelect', location.state);
|
console.log('previewSelect', location.state);
|
||||||
const componentRef = useRef(null);
|
const componentRef = useRef(null);
|
||||||
const [tabletype, settabletype] = useState(true);
|
|
||||||
const [paydialog, setpaydialog] = useState(false);
|
const [paydialog, setpaydialog] = useState(false);
|
||||||
const [refnumber, setRefnumber] = useState('');
|
const [refnumber, setRefnumber] = useState('');
|
||||||
const [remarks, setRemarks] = useState('');
|
const [remarks, setRemarks] = useState('');
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { enqueueSnackbar, closeSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
import AnimateButton from 'components/@extended/AnimateButton';
|
||||||
import OtpInput from 'react18-input-otp';
|
|
||||||
|
|
||||||
import { Box, Card, CardContent, Stack, TextField, Button, Typography, Link, FormLabel, IconButton, InputAdornment } from '@mui/material';
|
import { Box, Card, CardContent, Stack, TextField, Button, Typography, Link, FormLabel, IconButton, InputAdornment } from '@mui/material';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
@@ -11,7 +10,6 @@ import Loader from 'components/Loader';
|
|||||||
import doormileLogo from 'assets/images/doormile-logo.png';
|
import doormileLogo from 'assets/images/doormile-logo.png';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { OpenToast } from 'components/third-party/OpenToast';
|
import { OpenToast } from 'components/third-party/OpenToast';
|
||||||
import { closeGlobalToast, GlobalToast } from 'components/nearle_components/GlobalToast';
|
|
||||||
import Visibility from '@mui/icons-material/Visibility';
|
import Visibility from '@mui/icons-material/Visibility';
|
||||||
import VisibilityOff from '@mui/icons-material/VisibilityOff';
|
import VisibilityOff from '@mui/icons-material/VisibilityOff';
|
||||||
import { setLoginUser } from 'store/reducers/loginUserSlice';
|
import { setLoginUser } from 'store/reducers/loginUserSlice';
|
||||||
@@ -23,18 +21,15 @@ const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%)
|
|||||||
const Login = () => {
|
const Login = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const fcmtoken = useSelector((state) => state.fcm);
|
const fcmtoken = useSelector((state) => state.fcm);
|
||||||
const permission = useSelector((state) => state.fcm.permission);
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const [otp, setOtp] = useState('');
|
const [, setOtp] = useState('');
|
||||||
const [currentotp, setCurrentotp] = useState('');
|
|
||||||
const [userinfo, setUserinfo] = useState({});
|
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [passwordStatus, setPasswordStatus] = useState(0);
|
const [passwordStatus, setPasswordStatus] = useState(0);
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [confirmPassword, setConfirmPassword] = useState('');
|
const [confirmPassword, setConfirmPassword] = useState('');
|
||||||
const [isPassword, setIspassword] = useState(false);
|
const [isPassword] = useState(false);
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
const [showPassword, setShowPassword] = useState(false);
|
||||||
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
|
||||||
const [userid, setUserid] = useState(0);
|
const [userid, setUserid] = useState(0);
|
||||||
@@ -89,7 +84,6 @@ const Login = () => {
|
|||||||
// user found, correct password
|
// user found, correct password
|
||||||
else if (res.data.code == 200 && res.data.status) {
|
else if (res.data.code == 200 && res.data.status) {
|
||||||
OpenToast(res.data.message, 'success', 1000);
|
OpenToast(res.data.message, 'success', 1000);
|
||||||
setUserinfo(res.data.details);
|
|
||||||
const userinfo = res.data.details;
|
const userinfo = res.data.details;
|
||||||
dispatch(setLoginUser(userinfo));
|
dispatch(setLoginUser(userinfo));
|
||||||
localStorage.setItem('firstname', userinfo.firstname);
|
localStorage.setItem('firstname', userinfo.firstname);
|
||||||
@@ -113,21 +107,6 @@ const Login = () => {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const loginsuccessful = () => {
|
|
||||||
localStorage.setItem('firstname', userinfo.firstname);
|
|
||||||
localStorage.setItem('authname', userinfo.authname);
|
|
||||||
localStorage.setItem('roleid', userinfo.roleid);
|
|
||||||
localStorage.setItem('tenantid', userinfo.tenantid);
|
|
||||||
localStorage.setItem('partnerid', userinfo.partnerid);
|
|
||||||
localStorage.setItem('applocationid', userinfo.applocationid);
|
|
||||||
localStorage.setItem('userid', userinfo.userid);
|
|
||||||
localStorage.setItem('userfcmtoken', userinfo.userfcmtoken);
|
|
||||||
markSessionStart();
|
|
||||||
closeGlobalToast(); // to close the pin snackbar
|
|
||||||
|
|
||||||
navigate('/nearle/dispatch');
|
|
||||||
};
|
|
||||||
|
|
||||||
const opentoast = (message) => {
|
const opentoast = (message) => {
|
||||||
enqueueSnackbar(message, {
|
enqueueSnackbar(message, {
|
||||||
variant: 'error',
|
variant: 'error',
|
||||||
@@ -287,14 +266,6 @@ const Login = () => {
|
|||||||
}
|
}
|
||||||
loginsend();
|
loginsend();
|
||||||
}
|
}
|
||||||
// if (currentotp) {
|
|
||||||
// if (currentotp == otp) {
|
|
||||||
// loginsuccessful();
|
|
||||||
// fetchAppLocations();
|
|
||||||
// } else {
|
|
||||||
// opentoast('Invalid pin');
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
// import AuthWrapper from 'sections/auth/AuthWrapper';
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Grid,
|
Grid,
|
||||||
@@ -39,7 +37,7 @@ const Login = () => {
|
|||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [alertmessage, setAlertmessage] = useState('');
|
const [, setAlertmessage] = useState('');
|
||||||
const [checkusername, setCheckusername] = useState(false);
|
const [checkusername, setCheckusername] = useState(false);
|
||||||
// const [toast, setToast] = useState(false);
|
// const [toast, setToast] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -107,11 +105,8 @@ const Login = () => {
|
|||||||
// setCheckusername(false);
|
// setCheckusername(false);
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(() => {
|
||||||
// if (err.response.data.message === 'No user found') {
|
|
||||||
|
|
||||||
setCheckusername(true);
|
setCheckusername(true);
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -278,10 +273,6 @@ const Login = () => {
|
|||||||
<CardHeader title={<Typography variant="h3">Login</Typography>} />
|
<CardHeader title={<Typography variant="h3">Login</Typography>} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* <Grid item xs={12}>
|
|
||||||
<AuthLogin isDemo={isLoggedIn} />
|
|
||||||
</Grid> */}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<form
|
<form
|
||||||
@@ -516,4 +507,4 @@ const Login = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Login1;
|
export default Login;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
Backdrop,
|
Backdrop,
|
||||||
IconButton
|
IconButton
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import React, { Fragment, useEffect, useMemo, useState } from 'react';
|
import React, { Fragment, useEffect, useState } from 'react';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
||||||
@@ -32,7 +32,7 @@ import Loader from 'components/Loader';
|
|||||||
import CircularLoader from 'components/CircularLoader';
|
import CircularLoader from 'components/CircularLoader';
|
||||||
import { Empty } from 'antd';
|
import { Empty } from 'antd';
|
||||||
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
|
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
|
||||||
import { DashboardFilled, OpenAIFilled } from '@ant-design/icons';
|
import { DashboardFilled } from '@ant-design/icons';
|
||||||
import { MdDirectionsBike } from 'react-icons/md';
|
import { MdDirectionsBike } from 'react-icons/md';
|
||||||
import { FaMapLocationDot } from 'react-icons/fa6';
|
import { FaMapLocationDot } from 'react-icons/fa6';
|
||||||
import { HiOutlineArrowLeft } from 'react-icons/hi';
|
import { HiOutlineArrowLeft } from 'react-icons/hi';
|
||||||
@@ -234,9 +234,7 @@ const OrdersPreview = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
data: paymentModes = [],
|
data: paymentModes = [],
|
||||||
isLoading: paymentModesLoading,
|
isLoading: paymentModesLoading
|
||||||
isError: paymentModesError,
|
|
||||||
error: paymentModesErrorMessage
|
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ['paymentmodes'],
|
queryKey: ['paymentmodes'],
|
||||||
queryFn: fetchPaymentType
|
queryFn: fetchPaymentType
|
||||||
@@ -246,24 +244,13 @@ const OrdersPreview = () => {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
data: ridersList = [],
|
data: ridersList = [],
|
||||||
isLoading: ridersListLoading,
|
isLoading: ridersListLoading
|
||||||
isError: ridersListError,
|
|
||||||
error: ridersListErrorMessage,
|
|
||||||
refetch: ridersListRefetch
|
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ['ridersList', appId], // Unique key for caching & re-fetching
|
queryKey: ['ridersList', appId], // Unique key for caching & re-fetching
|
||||||
queryFn: fetchRidersList,
|
queryFn: fetchRidersList,
|
||||||
enabled: appId !== 0 // Ensures query runs only when appId is valid
|
enabled: appId !== 0 // Ensures query runs only when appId is valid
|
||||||
});
|
});
|
||||||
|
|
||||||
const getRiderName = async (userid) => {
|
|
||||||
await ridersList.map((rider) => {
|
|
||||||
if (rider.userid == userid) {
|
|
||||||
return rider.firstname;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// ======================================================= || notifyRiderMutation || =======================================================
|
// ======================================================= || notifyRiderMutation || =======================================================
|
||||||
|
|
||||||
const notifyRiderMutation = useMutation({
|
const notifyRiderMutation = useMutation({
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
TextField,
|
TextField,
|
||||||
Autocomplete,
|
Autocomplete,
|
||||||
Chip,
|
|
||||||
Divider,
|
Divider,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -19,7 +18,6 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
Switch,
|
Switch,
|
||||||
OutlinedInput,
|
OutlinedInput,
|
||||||
FormGroup,
|
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Box,
|
Box,
|
||||||
Card,
|
Card,
|
||||||
@@ -28,7 +26,7 @@ import {
|
|||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance';
|
import { calculateDrivingDistance, calculateTotalCharge } from '../../../utils/distance';
|
||||||
import { Empty } from 'antd';
|
import { Empty } from 'antd';
|
||||||
import { FaPhoneAlt, FaBox, FaBoxes, FaTruck, FaArrowRight, FaArrowLeft, FaCheck, FaRoute, FaMoneyBillWave, FaChartLine, FaReceipt, FaPaperPlane } from 'react-icons/fa';
|
import { FaPhoneAlt, FaBox, FaBoxes, FaArrowRight, FaArrowLeft, FaCheck, FaRoute, FaMoneyBillWave, FaChartLine, FaReceipt, FaPaperPlane } from 'react-icons/fa';
|
||||||
import { GiDoorHandle } from 'react-icons/gi';
|
import { GiDoorHandle } from 'react-icons/gi';
|
||||||
import { FaLandmarkDome } from 'react-icons/fa6';
|
import { FaLandmarkDome } from 'react-icons/fa6';
|
||||||
import ClearIcon from '@mui/icons-material/Clear';
|
import ClearIcon from '@mui/icons-material/Clear';
|
||||||
@@ -39,8 +37,6 @@ import axios from 'axios';
|
|||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import Geocode from 'react-geocode';
|
import Geocode from 'react-geocode';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import * as geolib from 'geolib';
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import { FaUser } from 'react-icons/fa6';
|
import { FaUser } from 'react-icons/fa6';
|
||||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
||||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||||
@@ -50,7 +46,7 @@ import dayjs from 'dayjs';
|
|||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
var utc = require('dayjs/plugin/utc');
|
var utc = require('dayjs/plugin/utc');
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
import { SearchOutlined, CloseOutlined, CalendarOutlined, ClockCircleOutlined, FileTextOutlined, MessageOutlined } from '@ant-design/icons';
|
import { SearchOutlined, CalendarOutlined, ClockCircleOutlined, FileTextOutlined, MessageOutlined } from '@ant-design/icons';
|
||||||
import MyLocationIcon from '@mui/icons-material/MyLocation';
|
import MyLocationIcon from '@mui/icons-material/MyLocation';
|
||||||
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
|
import HighlightOffIcon from '@mui/icons-material/HighlightOff';
|
||||||
import { OpenToast } from 'components/third-party/OpenToast';
|
import { OpenToast } from 'components/third-party/OpenToast';
|
||||||
@@ -58,7 +54,6 @@ import { MapContainer, TileLayer, Marker, Polyline, useMap } from 'react-leaflet
|
|||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import 'leaflet/dist/leaflet.css';
|
import 'leaflet/dist/leaflet.css';
|
||||||
import './OrdersRedesign.css';
|
import './OrdersRedesign.css';
|
||||||
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
import AnimateButton from 'components/@extended/AnimateButton';
|
||||||
|
|
||||||
const pickupIcon = typeof window !== 'undefined' ? new L.Icon({
|
const pickupIcon = typeof window !== 'undefined' ? new L.Icon({
|
||||||
@@ -192,14 +187,12 @@ const Createorder1 = () => {
|
|||||||
const tenantRef = useRef(null);
|
const tenantRef = useRef(null);
|
||||||
const [inputValue1, setInputValue1] = React.useState('');
|
const [inputValue1, setInputValue1] = React.useState('');
|
||||||
const [inputValue2, setInputValue2] = React.useState('');
|
const [inputValue2, setInputValue2] = React.useState('');
|
||||||
const [tenanatLocoId, setTenanatLocoId] = useState(localStorage.getItem('locationid'));
|
|
||||||
const [isLocation, setIsLocation] = useState(false);
|
|
||||||
const textFieldRef1 = useRef(null);
|
const textFieldRef1 = useRef(null);
|
||||||
const textFieldRef1a = useRef(null);
|
const textFieldRef1a = useRef(null);
|
||||||
const textFieldRef2 = useRef(null);
|
const textFieldRef2 = useRef(null);
|
||||||
const [appId, setAppId] = useState(0);
|
const [appId, setAppId] = useState(0);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [clientdetail, setClientdetail] = useState([]);
|
const [, setClientdetail] = useState([]);
|
||||||
const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY'));
|
const [startdate, setStartdate] = useState(dayjs().format('MM-DD-YYYY'));
|
||||||
// const [starttime, setStatrttime] = useState(`${dayjs().format('MM-DD-YYYY')} 08:00:00`);
|
// const [starttime, setStatrttime] = useState(`${dayjs().format('MM-DD-YYYY')} 08:00:00`);
|
||||||
const [starttime, setStatrttime] = useState();
|
const [starttime, setStatrttime] = useState();
|
||||||
@@ -224,16 +217,15 @@ const Createorder1 = () => {
|
|||||||
const [minKm, setMinKm] = useState(0);
|
const [minKm, setMinKm] = useState(0);
|
||||||
const [totalCharge, setTotalCharge] = useState(0);
|
const [totalCharge, setTotalCharge] = useState(0);
|
||||||
const [subCat, setSubCat] = useState([]);
|
const [subCat, setSubCat] = useState([]);
|
||||||
const [subCatName, setSubCatName] = useState('Select ');
|
const [, setSubCatName] = useState('Select ');
|
||||||
const [subCatId, setSubCatId] = useState(0);
|
const [subCatId, setSubCatId] = useState(0);
|
||||||
const [weight, setWeight] = useState('');
|
const [weight] = useState('');
|
||||||
const [tenantid, setTenantid] = useState(0);
|
const [tenantid, setTenantid] = useState(0);
|
||||||
const [locationid, setLocationid] = useState(0);
|
const [locationid, setLocationid] = useState(0);
|
||||||
const [selectedCatChip, setSelectedCatChip] = useState(null);
|
|
||||||
const [isCustomerOpen, setIsCustomerOpen] = useState(false);
|
const [isCustomerOpen, setIsCustomerOpen] = useState(false);
|
||||||
const [searchCustList, setSearchCustList] = useState('');
|
const [searchCustList, setSearchCustList] = useState('');
|
||||||
const [customerlist, setCustomerlist] = useState([]);
|
const [customerlist, setCustomerlist] = useState([]);
|
||||||
const [defaultPickup, setDefaultPickup] = useState(null);
|
const [, setDefaultPickup] = useState(null);
|
||||||
const [pickCust, setPickCust] = useState(null);
|
const [pickCust, setPickCust] = useState(null);
|
||||||
const [dropCust, setDropCust] = useState(null);
|
const [dropCust, setDropCust] = useState(null);
|
||||||
const [pickordrop, setpickordrop] = useState(0); // 1 ->pick 2 -> drop
|
const [pickordrop, setpickordrop] = useState(0); // 1 ->pick 2 -> drop
|
||||||
@@ -330,20 +322,6 @@ const Createorder1 = () => {
|
|||||||
appId && fetchtenantinfolist();
|
appId && fetchtenantinfolist();
|
||||||
}, [appId]);
|
}, [appId]);
|
||||||
|
|
||||||
const handleChipClick = (chipLabel) => {
|
|
||||||
setSelectedCatChip(chipLabel);
|
|
||||||
};
|
|
||||||
|
|
||||||
const chipStyle = (chipLabel) => ({
|
|
||||||
cursor: 'pointer',
|
|
||||||
backgroundColor: selectedCatChip === chipLabel ? theme.palette.primary.main : 'default',
|
|
||||||
color: selectedCatChip === chipLabel ? '#fff' : '',
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: selectedCatChip === chipLabel ? theme.palette.primary.main : theme.palette.primary.light,
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetchTenantPricing = async (id) => {
|
const fetchTenantPricing = async (id) => {
|
||||||
try {
|
try {
|
||||||
const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${id}`);
|
const pricingResponse = await axios.get(`${process.env.REACT_APP_URL}/tenants/gettenantpricing/?tenantid=${id}`);
|
||||||
@@ -473,9 +451,9 @@ const Createorder1 = () => {
|
|||||||
console.log('endtime', `${dayjs().format('MM-DD-YYYY')} ${closetime} `);
|
console.log('endtime', `${dayjs().format('MM-DD-YYYY')} ${closetime} `);
|
||||||
let arr = [];
|
let arr = [];
|
||||||
for (
|
for (
|
||||||
let i = `${dayjs().format('MM-DD-YYYY')} ${opentime}`, j = 0;
|
let i = `${dayjs().format('MM-DD-YYYY')} ${opentime}`;
|
||||||
dayjs(`${dayjs().format('MM-DD-YYYY')} ${closetime} `).diff(i, 'm') >= 0;
|
dayjs(`${dayjs().format('MM-DD-YYYY')} ${closetime} `).diff(i, 'm') >= 0;
|
||||||
j++, i = dayjs(i).add(30, 'm')
|
i = dayjs(i).add(30, 'm')
|
||||||
) {
|
) {
|
||||||
arr.push(i);
|
arr.push(i);
|
||||||
}
|
}
|
||||||
@@ -859,7 +837,6 @@ const Createorder1 = () => {
|
|||||||
// radius: 100000 //km to m
|
// radius: 100000 //km to m
|
||||||
}).getBounds()
|
}).getBounds()
|
||||||
});
|
});
|
||||||
let arr = [];
|
|
||||||
// Event listener for autocomplete place changed
|
// Event listener for autocomplete place changed
|
||||||
autocomplete.addListener('place_changed', () => {
|
autocomplete.addListener('place_changed', () => {
|
||||||
const place = autocomplete.getPlace();
|
const place = autocomplete.getPlace();
|
||||||
|
|||||||
@@ -1,39 +1,15 @@
|
|||||||
import {
|
import { useEffect, useState, Fragment } from 'react';
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
Fragment
|
|
||||||
// useReducer
|
|
||||||
} from 'react';
|
|
||||||
import BorderColorIcon from '@mui/icons-material/BorderColor';
|
import BorderColorIcon from '@mui/icons-material/BorderColor';
|
||||||
import {
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
// Navigate,
|
|
||||||
// useSearchParams,
|
|
||||||
useLocation,
|
|
||||||
useNavigate
|
|
||||||
} from 'react-router-dom';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import {
|
import { EnvironmentOutlined, EditTwoTone } from '@ant-design/icons';
|
||||||
// UserOutlined,
|
|
||||||
EnvironmentOutlined,
|
|
||||||
EditTwoTone
|
|
||||||
// DeleteTwoTone
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
// import WomanIcon from '@mui/icons-material/Woman';
|
|
||||||
// import { Link } from 'react-router-dom';
|
|
||||||
// import SoupKitchenIcon from '@mui/icons-material/SoupKitchen';
|
|
||||||
import DirectionsCarIcon from '@mui/icons-material/DirectionsCar';
|
import DirectionsCarIcon from '@mui/icons-material/DirectionsCar';
|
||||||
import { KeyboardArrowUp, KeyboardArrowDown } from '@mui/icons-material';
|
import { KeyboardArrowUp, KeyboardArrowDown } from '@mui/icons-material';
|
||||||
|
|
||||||
// import { PopupTransition } from 'components/@extended/Transitions';
|
|
||||||
// import { useDispatch } from 'react-redux';
|
|
||||||
// import { openSnackbar } from 'store/reducers/snackbar';
|
|
||||||
// assets
|
// assets
|
||||||
import { DeleteFilled, NotificationOutlined } from '@ant-design/icons';
|
import { DeleteFilled, NotificationOutlined } from '@ant-design/icons';
|
||||||
var utc = require('dayjs/plugin/utc');
|
var utc = require('dayjs/plugin/utc');
|
||||||
// import { groupBy } from "core-js/actual/array/group-by";
|
|
||||||
// import "lodash.chunk";
|
|
||||||
// var chunk = require('lodash.chunk');
|
|
||||||
import {
|
import {
|
||||||
Grid,
|
Grid,
|
||||||
Typography,
|
Typography,
|
||||||
@@ -79,13 +55,8 @@ import { PopupTransition } from 'components/@extended/Transitions';
|
|||||||
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
|
import CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';
|
||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
// import AlertCustomerDelete from 'sections/apps/customer/AlertCustomerDelete';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
// import { Link as RouterLink } from 'react-router-dom';
|
|
||||||
// import PlayCircleFilled from '@mui/icons-material/PlayCircleFilled';
|
|
||||||
// import SmileFilled from '@mui/icons-material/Mood';
|
|
||||||
// import HeartFilled from '@mui/icons-material/Favorite';
|
|
||||||
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
@@ -181,23 +152,6 @@ const Details = () => {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
// const fetchorderdetails = async () => {
|
|
||||||
// setLoading(true);
|
|
||||||
// await axios
|
|
||||||
// .get(`${process.env.REACT_APP_URL}/orders/orderbyid/?orderheaderid=${orderheaderid}`)
|
|
||||||
|
|
||||||
// .then((res) => {
|
|
||||||
// console.log(res);
|
|
||||||
|
|
||||||
// setLoading(false);
|
|
||||||
// })
|
|
||||||
// .catch((err) => {
|
|
||||||
// console.log(err);
|
|
||||||
// setLoading(false);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// };
|
|
||||||
|
|
||||||
const fetchorderaddons = async () => {
|
const fetchorderaddons = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await axios
|
await axios
|
||||||
@@ -249,21 +203,6 @@ const Details = () => {
|
|||||||
console.log('res');
|
console.log('res');
|
||||||
console.log(res);
|
console.log(res);
|
||||||
setOrderarr(res.data.Details || []);
|
setOrderarr(res.data.Details || []);
|
||||||
// let result = res.data.Details.find((res1) => res1.orderheaderid == searchParams.get('id'))
|
|
||||||
// orderheaderid
|
|
||||||
// console.log(result)
|
|
||||||
// setOrderaddons(result.orderaddons);
|
|
||||||
// setVenuetype(result.venuetype)
|
|
||||||
// setOtherinstructions(result.remarks)
|
|
||||||
// console.log("res");
|
|
||||||
// let result = _.chain(res.data.Details)
|
|
||||||
|
|
||||||
// .groupBy("shiftid")
|
|
||||||
|
|
||||||
// .map((value, key) => ({shiftid:key, locationaddress: value[0].locationaddress, roles: value }))
|
|
||||||
// .value()
|
|
||||||
|
|
||||||
// setcategoryarr(result);
|
|
||||||
console.log('categoryarr');
|
console.log('categoryarr');
|
||||||
setcategoryarr(res.data.Details);
|
setcategoryarr(res.data.Details);
|
||||||
console.log(res.data.Details);
|
console.log(res.data.Details);
|
||||||
@@ -305,15 +244,7 @@ const Details = () => {
|
|||||||
const cancelorder = async () => {
|
const cancelorder = async () => {
|
||||||
await axios
|
await axios
|
||||||
.put(`${process.env.REACT_APP_URL2}/orders/cancel`, {
|
.put(`${process.env.REACT_APP_URL2}/orders/cancel`, {
|
||||||
// "Orderheaderid": parseInt(orderheaderid),
|
|
||||||
// "Tenantid": parseInt(tenantid),
|
|
||||||
// "Orderstatus": "cancelled",
|
|
||||||
// "Currentdatetime": dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
// "Cod": false,
|
|
||||||
// "Remarks": "",
|
|
||||||
orderheaderid: parseInt(orderheaderid),
|
orderheaderid: parseInt(orderheaderid),
|
||||||
// "orderdetailid":78,
|
|
||||||
// "shiftid":788,
|
|
||||||
orderstatus: 'cancelled',
|
orderstatus: 'cancelled',
|
||||||
cancelled: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
cancelled: dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
||||||
unserviceable: invoiceeligible ? 0 : 1
|
unserviceable: invoiceeligible ? 0 : 1
|
||||||
@@ -443,20 +374,10 @@ const Details = () => {
|
|||||||
fetchorderaddons();
|
fetchorderaddons();
|
||||||
fetchorderattires();
|
fetchorderattires();
|
||||||
fetchassignedcount();
|
fetchassignedcount();
|
||||||
// fetchuserdetails();
|
|
||||||
console.log(location.state || '');
|
console.log(location.state || '');
|
||||||
// setOrderid(location.state.orderid || '');
|
|
||||||
// setEventlocation(location.state.eventlocation || '');
|
|
||||||
// setEventlocation(address || []);
|
|
||||||
|
|
||||||
// setOrderdate(dayjs(location.state.orderdate.substring(0, 10)).format('MM/DD/YYYY') || '');
|
|
||||||
// setDuedate(dayjs(location.state.orderdate.substring(0, 10)).format('MM/DD/YYYY') || '')
|
|
||||||
// setEventname(location.state.eventname || '');
|
|
||||||
// setClientname(location.state.tenantname || '')
|
|
||||||
} else {
|
} else {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
// fetchorderdetails();
|
|
||||||
console.log(orderheaderid, tenantid);
|
console.log(orderheaderid, tenantid);
|
||||||
}, [orderheaderid, tenantid, assignedpendingcount]);
|
}, [orderheaderid, tenantid, assignedpendingcount]);
|
||||||
|
|
||||||
@@ -522,12 +443,6 @@ const Details = () => {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
if (res.data.message === 'Successfully created') {
|
if (res.data.message === 'Successfully created') {
|
||||||
// if (orderheaderid && tenantid) {
|
|
||||||
// fetchorderdetails();
|
|
||||||
// fetchorderaddons();
|
|
||||||
// fetchorderattires();
|
|
||||||
// }
|
|
||||||
|
|
||||||
enqueueSnackbar('Roles assigned successfully', {
|
enqueueSnackbar('Roles assigned successfully', {
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||||
@@ -631,32 +546,6 @@ const Details = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// const updateorderstatus = async () => {
|
|
||||||
|
|
||||||
// await axios.put(`${process.env.REACT_APP_URL2}/orders/updateorderstatus`,{
|
|
||||||
// "orderheaderid":orderheaderid,
|
|
||||||
// "tenantid":tenantid,
|
|
||||||
// "orderstatus":"processing",
|
|
||||||
// "pending":"",
|
|
||||||
// "processing":dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
||||||
// "completed":""
|
|
||||||
// })
|
|
||||||
// .then((res) => {
|
|
||||||
// console.log(res)
|
|
||||||
// fetchorderdetails();
|
|
||||||
// fetchorderaddons();
|
|
||||||
// fetchorderattires();
|
|
||||||
|
|
||||||
// })
|
|
||||||
// .catch((err) => {
|
|
||||||
// console.log(err)
|
|
||||||
// fetchorderdetails();
|
|
||||||
// fetchorderaddons();
|
|
||||||
// fetchorderattires();
|
|
||||||
// })
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
const fetchassignedcount = async () => {
|
const fetchassignedcount = async () => {
|
||||||
// console.log(obj1)
|
// console.log(obj1)
|
||||||
await axios
|
await axios
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ import {
|
|||||||
CalendarOutlined,
|
CalendarOutlined,
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
InboxOutlined,
|
InboxOutlined
|
||||||
LockOutlined,
|
|
||||||
CheckCircleFilled
|
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { Empty } from 'antd';
|
import { Empty } from 'antd';
|
||||||
import { FaUser, FaTruck, FaUsers, FaPaperPlane, FaRoute, FaMoneyBillWave, FaBoxes, FaReceipt } from 'react-icons/fa';
|
import { FaUser, FaTruck, FaUsers, FaPaperPlane, FaRoute, FaMoneyBillWave, FaBoxes, FaReceipt } from 'react-icons/fa';
|
||||||
@@ -66,7 +64,6 @@ import { MdOutlineCloudUpload } from 'react-icons/md';
|
|||||||
|
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import CircularLoader from 'components/CircularLoader';
|
import CircularLoader from 'components/CircularLoader';
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
||||||
import './OrdersRedesign.css';
|
import './OrdersRedesign.css';
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useState, useEffect, Fragment, useRef } from 'react';
|
import { useState, useEffect, Fragment, useRef } from 'react';
|
||||||
import { DashboardOutlined, DeleteFilled, DeleteOutlined, ShoppingCartOutlined } from '@ant-design/icons';
|
import { DeleteFilled, DeleteOutlined, ShoppingCartOutlined } from '@ant-design/icons';
|
||||||
import { Empty } from 'antd';
|
import { Empty } from 'antd';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
|
import { useQuery, useMutation, useInfiniteQuery } from '@tanstack/react-query';
|
||||||
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import { CloseOutlined } from '@ant-design/icons';
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import { PopupTransition } from 'components/@extended/Transitions';
|
import { PopupTransition } from 'components/@extended/Transitions';
|
||||||
@@ -12,9 +11,7 @@ import CircularLoader from 'components/CircularLoader';
|
|||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import { KeyboardArrowDownOutlined, KeyboardArrowUpOutlined } from '@mui/icons-material';
|
import { KeyboardArrowDownOutlined, KeyboardArrowUpOutlined } from '@mui/icons-material';
|
||||||
|
|
||||||
import { PiMapPinLineDuotone } from 'react-icons/pi';
|
|
||||||
import {
|
import {
|
||||||
MdOutlineDateRange,
|
|
||||||
MdPersonOff,
|
MdPersonOff,
|
||||||
MdEventBusy,
|
MdEventBusy,
|
||||||
MdLocalShipping,
|
MdLocalShipping,
|
||||||
@@ -28,16 +25,11 @@ import {
|
|||||||
MdMyLocation,
|
MdMyLocation,
|
||||||
MdGroups,
|
MdGroups,
|
||||||
MdPlace,
|
MdPlace,
|
||||||
MdStraighten,
|
|
||||||
MdCurrencyRupee,
|
|
||||||
MdInventory2,
|
|
||||||
MdHistoryToggleOff,
|
MdHistoryToggleOff,
|
||||||
MdCalendarMonth
|
MdCalendarMonth
|
||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
import { VscArchive } from 'react-icons/vsc';
|
|
||||||
import DateFilterDialog from 'components/DateFilterDialog';
|
import DateFilterDialog from 'components/DateFilterDialog';
|
||||||
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
||||||
import TitleCard from 'components/nearle_components/TitleCard';
|
|
||||||
import MainCard from 'components/MainCard';
|
import MainCard from 'components/MainCard';
|
||||||
import { OpenToast } from 'components/third-party/OpenToast';
|
import { OpenToast } from 'components/third-party/OpenToast';
|
||||||
import { OrdersTableSkeleton } from './OrdersTableSkeleton';
|
import { OrdersTableSkeleton } from './OrdersTableSkeleton';
|
||||||
@@ -46,11 +38,6 @@ import PageHeader from 'components/nearle_components/PageHeader';
|
|||||||
import StatCard from 'components/nearle_components/StatCard';
|
import StatCard from 'components/nearle_components/StatCard';
|
||||||
import AiImage from '../../../assets/images/aiImage.png';
|
import AiImage from '../../../assets/images/aiImage.png';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import EnergySavingsLeafIcon from '@mui/icons-material/EnergySavingsLeaf';
|
|
||||||
import DirectionsBikeOutlinedIcon from '@mui/icons-material/DirectionsBikeOutlined';
|
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
|
||||||
import BoltIcon from '@mui/icons-material/Bolt';
|
|
||||||
import { ArrowRightAltOutlined } from '@mui/icons-material';
|
|
||||||
import { HiOutlineArrowLeft } from 'react-icons/hi';
|
import { HiOutlineArrowLeft } from 'react-icons/hi';
|
||||||
|
|
||||||
import { IoReload } from 'react-icons/io5';
|
import { IoReload } from 'react-icons/io5';
|
||||||
@@ -62,8 +49,6 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
Grid,
|
Grid,
|
||||||
Tabs,
|
|
||||||
Tab,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
Stack,
|
Stack,
|
||||||
TextField,
|
TextField,
|
||||||
@@ -89,9 +74,6 @@ import {
|
|||||||
SpeedDialAction,
|
SpeedDialAction,
|
||||||
Badge,
|
Badge,
|
||||||
Divider,
|
Divider,
|
||||||
AccordionDetails,
|
|
||||||
AccordionSummary,
|
|
||||||
Accordion,
|
|
||||||
Paper,
|
Paper,
|
||||||
Box
|
Box
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
@@ -118,7 +100,6 @@ import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'compon
|
|||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
import CSVExport from 'components/third-party/ReactTable';
|
import CSVExport from 'components/third-party/ReactTable';
|
||||||
import Dispatch from '../dispatch/Dispatch';
|
import Dispatch from '../dispatch/Dispatch';
|
||||||
// import usePreventReload from 'hooks/usePreventReload';
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Design tokens — shared with deliveries / tenants / customers / pricing /
|
// Design tokens — shared with deliveries / tenants / customers / pricing /
|
||||||
@@ -255,8 +236,8 @@ const Orders = () => {
|
|||||||
const [dispatchPreviewData, setDispatchPreviewData] = useState(null);
|
const [dispatchPreviewData, setDispatchPreviewData] = useState(null);
|
||||||
const [deliverylist, setDeliverylist] = useState([]);
|
const [deliverylist, setDeliverylist] = useState([]);
|
||||||
const [deliveryDetails, setDeliveryDetails] = useState([]);
|
const [deliveryDetails, setDeliveryDetails] = useState([]);
|
||||||
const [zoneData, setZoneData] = useState(null);
|
const [, setZoneData] = useState(null);
|
||||||
const [metaData, setMetaData] = useState(null);
|
const [, setMetaData] = useState(null);
|
||||||
const [aiMode] = useState(0);
|
const [aiMode] = useState(0);
|
||||||
const [csvExportData, setCsvExportData] = useState([]);
|
const [csvExportData, setCsvExportData] = useState([]);
|
||||||
const [finaldeliveryList, setFinalDeliveryList] = useState([]);
|
const [finaldeliveryList, setFinalDeliveryList] = useState([]);
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
import React, { useEffect, useRef } from 'react';
|
|
||||||
import { LoadScriptNext, GoogleMap } from '@react-google-maps/api';
|
|
||||||
|
|
||||||
const containerStyle = {
|
|
||||||
width: '100%',
|
|
||||||
height: '90vh'
|
|
||||||
};
|
|
||||||
|
|
||||||
const MapWithRouteGoogle = ({ coordinates, additionalProps, setMapOpen }) => {
|
|
||||||
const mapRef = useRef(null);
|
|
||||||
|
|
||||||
/** Convert coordinates to numbers */
|
|
||||||
const numericCoordinates = coordinates
|
|
||||||
.map((c) => {
|
|
||||||
const lat = Number(c.lat);
|
|
||||||
const lng = Number(c.lng);
|
|
||||||
return isNaN(lat) || isNaN(lng) ? null : { lat, lng };
|
|
||||||
})
|
|
||||||
.filter(Boolean);
|
|
||||||
|
|
||||||
if (numericCoordinates.length < 2) {
|
|
||||||
return <div>No route data available</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = numericCoordinates[0];
|
|
||||||
const end = numericCoordinates[numericCoordinates.length - 1];
|
|
||||||
|
|
||||||
/** Map loaded callback */
|
|
||||||
const onMapLoad = (map) => {
|
|
||||||
// draw markers
|
|
||||||
new window.google.maps.Marker({
|
|
||||||
position: start,
|
|
||||||
map,
|
|
||||||
label: 'S',
|
|
||||||
title: `Start: ${additionalProps?.riderStart}`
|
|
||||||
});
|
|
||||||
|
|
||||||
new window.google.maps.Marker({
|
|
||||||
position: end,
|
|
||||||
map,
|
|
||||||
label: 'E',
|
|
||||||
title: `End: ${additionalProps?.riderEnd}`
|
|
||||||
});
|
|
||||||
|
|
||||||
// draw rider route (point-to-point)
|
|
||||||
const route = new window.google.maps.Polyline({
|
|
||||||
path: numericCoordinates,
|
|
||||||
geodesic: false,
|
|
||||||
strokeColor: '#1A73E8',
|
|
||||||
strokeOpacity: 1.0,
|
|
||||||
strokeWeight: 4
|
|
||||||
});
|
|
||||||
|
|
||||||
route.setMap(map);
|
|
||||||
|
|
||||||
// auto fit
|
|
||||||
const bounds = new window.google.maps.LatLngBounds();
|
|
||||||
numericCoordinates.forEach((p) => bounds.extend(p));
|
|
||||||
map.fitBounds(bounds);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
onClick={() => setMapOpen(false)}
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
zIndex: 999,
|
|
||||||
padding: '6px 12px',
|
|
||||||
background: '#1A73E8',
|
|
||||||
color: 'white',
|
|
||||||
borderRadius: 6,
|
|
||||||
cursor: 'pointer',
|
|
||||||
border: 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<LoadScriptNext googleMapsApiKey={process.env.REACT_APP_GOOGLE_MAPS_API_KEY}>
|
|
||||||
<GoogleMap mapContainerStyle={containerStyle} center={start} zoom={14} onLoad={onMapLoad}>
|
|
||||||
{/* Polyline and markers added via onLoad */}
|
|
||||||
</GoogleMap>
|
|
||||||
</LoadScriptNext>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MapWithRouteGoogle;
|
|
||||||
@@ -16,8 +16,6 @@ import {
|
|||||||
Divider,
|
Divider,
|
||||||
Grid,
|
Grid,
|
||||||
IconButton,
|
IconButton,
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
@@ -51,7 +49,6 @@ import {
|
|||||||
MdCheckCircle,
|
MdCheckCircle,
|
||||||
MdCancel,
|
MdCancel,
|
||||||
MdList,
|
MdList,
|
||||||
MdLocalShipping,
|
|
||||||
MdStraighten,
|
MdStraighten,
|
||||||
MdCurrencyRupee,
|
MdCurrencyRupee,
|
||||||
MdMap,
|
MdMap,
|
||||||
|
|||||||
@@ -242,23 +242,6 @@ const Requests = () => {
|
|||||||
// fetchroleslist();
|
// fetchroleslist();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
|
|
||||||
// if (alertmessage && toast) {
|
|
||||||
// dispatch(
|
|
||||||
// openSnackbar({
|
|
||||||
// open: true,
|
|
||||||
// message: alertmessage,
|
|
||||||
// variant: 'alert',
|
|
||||||
// anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
// alert: {
|
|
||||||
// color: 'error',
|
|
||||||
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }, [toast])
|
|
||||||
const opentoast = (message) => {
|
const opentoast = (message) => {
|
||||||
enqueueSnackbar(message, {
|
enqueueSnackbar(message, {
|
||||||
variant: 'error',
|
variant: 'error',
|
||||||
@@ -486,17 +469,6 @@ const Requests = () => {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log('res:', res);
|
console.log('res:', res);
|
||||||
if (res.data.message === 'Update successful') {
|
if (res.data.message === 'Update successful') {
|
||||||
// dispatch(
|
|
||||||
// openSnackbar({
|
|
||||||
// open: true,
|
|
||||||
// message: 'Client Detail Updated Successfully',
|
|
||||||
// variant: 'alert',
|
|
||||||
// anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
// alert: {
|
|
||||||
// color: 'success'
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// )
|
|
||||||
enqueueSnackbar('Client Details Updated Successfully', {
|
enqueueSnackbar('Client Details Updated Successfully', {
|
||||||
variant: 'success',
|
variant: 'success',
|
||||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||||
@@ -626,63 +598,6 @@ const Requests = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const rolepriceupdate = async () => {
|
|
||||||
// console.log('submit')
|
|
||||||
// let arr = [];
|
|
||||||
// let objcheck = false;
|
|
||||||
// rolesarr.map((val) => {
|
|
||||||
// if (!val.role || !val.cost) {
|
|
||||||
// objcheck = true;
|
|
||||||
// }
|
|
||||||
// arr.push({
|
|
||||||
// serviceid: 0,
|
|
||||||
// tenantid: currenttenantid,
|
|
||||||
// categoryid: val.categoryid,
|
|
||||||
// subcategoryid: val.subcategoryid,
|
|
||||||
// servicecode: val.servicecode,
|
|
||||||
// servicename: val.servicename,
|
|
||||||
// unitid: val.unitid,
|
|
||||||
// unitname: val.unitname,
|
|
||||||
// serviceamount: parseFloat(val.serviceamount),
|
|
||||||
// discountid: val.discountid,
|
|
||||||
// taxpercent: val.taxpercent,
|
|
||||||
// taxamount: val.taxamount,
|
|
||||||
// servicevalue: parseFloat(val.servicevalue),
|
|
||||||
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// console.log(arr)
|
|
||||||
// if (!objcheck) {
|
|
||||||
// try {
|
|
||||||
// setLoading(true)
|
|
||||||
// // await axios.post(`${process.env.REACT_APP_URL2}/clients/createservice`, arr)
|
|
||||||
// await axios.post(`${process.env.REACT_APP_URL2}/tenants/createservice`, arr)
|
|
||||||
|
|
||||||
// // await axios.post(`${process.env.REACT_APP_URL2}/clients/createservice`, arr)
|
|
||||||
// .then((res) => {
|
|
||||||
// console.log('res:', res);
|
|
||||||
// if (res.data.message === "Successful") {
|
|
||||||
|
|
||||||
// enqueueSnackbar('Service created Successfully', { variant: 'success',anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
// autoHideDuration: 3000 })
|
|
||||||
// }
|
|
||||||
// setLoading(false)
|
|
||||||
// }).catch((err) => {
|
|
||||||
// console.log(err)
|
|
||||||
// setLoading(false)
|
|
||||||
// })
|
|
||||||
|
|
||||||
// } catch (err) {
|
|
||||||
// console.log(err);
|
|
||||||
// setLoading(false)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
|
|
||||||
// enqueueSnackbar('Fill all Details', { variant: 'error',anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
|
||||||
// autoHideDuration: 2000 })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const handleRequestSort = (event, property) => {
|
const handleRequestSort = (event, property) => {
|
||||||
const isAsc = orderBy === property && order === 'asc';
|
const isAsc = orderBy === property && order === 'asc';
|
||||||
setOrder(isAsc ? 'desc' : 'asc');
|
setOrder(isAsc ? 'desc' : 'asc');
|
||||||
@@ -811,15 +726,9 @@ const Requests = () => {
|
|||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
value={amount}
|
value={amount}
|
||||||
// placeholder='Mobile Number'
|
|
||||||
// InputProps={{
|
|
||||||
// startAdornment: <InputAdornment position="start">+1</InputAdornment>,
|
|
||||||
// }}
|
|
||||||
sx={{ width: '100%' }}
|
sx={{ width: '100%' }}
|
||||||
onChange={(e) => setAmount(e.target.value)}
|
onChange={(e) => setAmount(e.target.value)}
|
||||||
/>
|
/>
|
||||||
{/* </Stack>
|
|
||||||
</List> */}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
{/* </Grid>
|
{/* </Grid>
|
||||||
</MainCard>
|
</MainCard>
|
||||||
@@ -918,7 +827,7 @@ const Requests = () => {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{!loading &&
|
{!loading &&
|
||||||
visibleRows.map((row, index) => {
|
visibleRows.map((row) => {
|
||||||
const isItemSelected = isSelected(row.sno);
|
const isItemSelected = isSelected(row.sno);
|
||||||
return (
|
return (
|
||||||
<MobileCard
|
<MobileCard
|
||||||
@@ -1468,10 +1377,6 @@ const Requests = () => {
|
|||||||
border: '1px solid #e0e0e0',
|
border: '1px solid #e0e0e0',
|
||||||
textIndent: '10px',
|
textIndent: '10px',
|
||||||
outline: 'none'
|
outline: 'none'
|
||||||
// ':hover': {
|
|
||||||
// border: '1px solid #00b0ff !important',
|
|
||||||
// backgroundColor:'blue'
|
|
||||||
// }
|
|
||||||
}}
|
}}
|
||||||
onPlaceSelected={(place) => {
|
onPlaceSelected={(place) => {
|
||||||
setAddress(place.formatted_address);
|
setAddress(place.formatted_address);
|
||||||
@@ -1813,20 +1718,6 @@ const Requests = () => {
|
|||||||
const [searchword, setSearchword] = useState('');
|
const [searchword, setSearchword] = useState('');
|
||||||
const [dialogopen, setDialogopen] = useState(false);
|
const [dialogopen, setDialogopen] = useState(false);
|
||||||
|
|
||||||
// const [expandopen, setExpandopen] = React.useState('');
|
|
||||||
|
|
||||||
// const setinitial = (val)=>{
|
|
||||||
// if(val){
|
|
||||||
|
|
||||||
// console.log(val);
|
|
||||||
// setClientname(val.tenantname)
|
|
||||||
// }else{
|
|
||||||
// setClientname('')
|
|
||||||
// }
|
|
||||||
// console.log(clientname)
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (localStorage.getItem('partnerid')) {
|
if (localStorage.getItem('partnerid')) {
|
||||||
clientdetailspending(localStorage.getItem('partnerid'));
|
clientdetailspending(localStorage.getItem('partnerid'));
|
||||||
@@ -1834,33 +1725,6 @@ const Requests = () => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// if (searchword) {
|
|
||||||
// if (tabvalue === 0) {
|
|
||||||
// let arr = clientapproved.filter((val) => {
|
|
||||||
// return (val.tenantname.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.primarycontact.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.primaryemail.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.city.toString().toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
// console.log(arr)
|
|
||||||
// setRows([...arr])
|
|
||||||
// }
|
|
||||||
// if (tabvalue === 1) {
|
|
||||||
// let arr = clientpending.filter((val) => {
|
|
||||||
// return (val.tenantname.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.primarycontact.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.primaryemail.toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// || val.city.toString().toLowerCase().includes(searchword.toLowerCase())
|
|
||||||
// )
|
|
||||||
// })
|
|
||||||
// console.log(arr)
|
|
||||||
// setRows([...arr])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}, [searchword, tabvalue]);
|
|
||||||
|
|
||||||
const handleChangetab = (e, i) => {
|
const handleChangetab = (e, i) => {
|
||||||
setTabvalue(i);
|
setTabvalue(i);
|
||||||
if (i === 1) setRows(clientapproved);
|
if (i === 1) setRows(clientapproved);
|
||||||
|
|||||||
@@ -16,23 +16,8 @@ import Loader from 'components/Loader';
|
|||||||
import Geocode from 'react-geocode';
|
import Geocode from 'react-geocode';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
// import { setLocationType } from 'react-geocode';
|
|
||||||
|
|
||||||
// const avatarImage = require.context('assets/images/users', true);
|
|
||||||
|
|
||||||
// styles & constant
|
|
||||||
// const ITEM_HEIGHT = 48;
|
|
||||||
// const ITEM_PADDING_TOP = 8;
|
|
||||||
// const MenuProps = {
|
|
||||||
// PaperProps: {
|
|
||||||
// style: {
|
|
||||||
// maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const Createrider = () => {
|
const Createrider = () => {
|
||||||
// const [role, setRole] = useState('');
|
|
||||||
const [mobilenumber, setMobilenumber] = useState('');
|
const [mobilenumber, setMobilenumber] = useState('');
|
||||||
const [emailaddress, setEmailaddress] = useState('');
|
const [emailaddress, setEmailaddress] = useState('');
|
||||||
const [city, setCity] = useState('');
|
const [city, setCity] = useState('');
|
||||||
@@ -162,12 +147,6 @@ const Createrider = () => {
|
|||||||
const createprofile = async () => {
|
const createprofile = async () => {
|
||||||
console.log('res', businessname, businessno, mobilenumber, emailaddress, address, city, zipcode);
|
console.log('res', businessname, businessno, mobilenumber, emailaddress, address, city, zipcode);
|
||||||
|
|
||||||
// if (!businessname) {
|
|
||||||
// opentoast('Fill Business name')
|
|
||||||
// } else if (!businessno) {
|
|
||||||
// opentoast('Fill Registration No')
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
if (!firstname) {
|
if (!firstname) {
|
||||||
opentoast('Fill Full name');
|
opentoast('Fill Full name');
|
||||||
} else if (!mobilenumber) {
|
} else if (!mobilenumber) {
|
||||||
|
|||||||
@@ -164,38 +164,10 @@ const EditRider = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// const fetchpartnerlist = async () => {
|
|
||||||
// setLoading(true);
|
|
||||||
// await axios
|
|
||||||
// .get(`${process.env.REACT_APP_URL}/partners/getpartners`)
|
|
||||||
// .then((res) => {
|
|
||||||
// console.log('fetchpartnerlist', res);
|
|
||||||
// // if (res.data.status) {
|
|
||||||
// let arr = [];
|
|
||||||
// res.data.details.map((val) => {
|
|
||||||
// arr.push({
|
|
||||||
// ...val,
|
|
||||||
// label: val.partnername
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// setPartnerlist([...arr]);
|
|
||||||
// console.log(arr);
|
|
||||||
// // }
|
|
||||||
// setLoading(false);
|
|
||||||
// })
|
|
||||||
// .catch((err) => {
|
|
||||||
// console.log(err);
|
|
||||||
// setLoading(false);
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
// ==============================|| fetchAppLocations ||============================== //
|
// ==============================|| fetchAppLocations ||============================== //
|
||||||
const fetchAppLocations = async () => {
|
const fetchAppLocations = async () => {
|
||||||
try {
|
try {
|
||||||
const locationRes = await axios.get(`${process.env.REACT_APP_URL}/partners/getlocations/?userid=${userid}`);
|
const locationRes = await axios.get(`${process.env.REACT_APP_URL}/partners/getlocations/?userid=${userid}`);
|
||||||
// const updatedLocations = [
|
|
||||||
// ...locationRes.data.details,
|
|
||||||
// { locationname: 'All', applocationid: 0 } // Add your new object here
|
|
||||||
// ];
|
|
||||||
console.log('fetchAppLocations', locationRes.data.details);
|
console.log('fetchAppLocations', locationRes.data.details);
|
||||||
setPartnerlist(locationRes.data.details);
|
setPartnerlist(locationRes.data.details);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -398,7 +398,7 @@ const Riders = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: activeSubsToday, isLoading: activeSubsTodayLoading } = useQuery({
|
useQuery({
|
||||||
queryKey: ['activeSubstitutionsToday', appId, selectedDate.format('YYYY-MM-DD')],
|
queryKey: ['activeSubstitutionsToday', appId, selectedDate.format('YYYY-MM-DD')],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/// <reference types="react-scripts" />
|
|
||||||
@@ -1,17 +1,10 @@
|
|||||||
import { lazy } from 'react';
|
import { lazy } from 'react';
|
||||||
|
|
||||||
// project import
|
// project import
|
||||||
// import GuestGuard from 'utils/route-guard/GuestGuard';
|
|
||||||
import CommonLayout from 'layout/CommonLayout';
|
import CommonLayout from 'layout/CommonLayout';
|
||||||
import Loadable from 'components/Loadable';
|
import Loadable from 'components/Loadable';
|
||||||
|
|
||||||
// render - login
|
// render - login
|
||||||
// const AuthLogin = Loadable(lazy(() => import('pages/auth/login')));
|
|
||||||
// const AuthRegister = Loadable(lazy(() => import('pages/auth/register')));
|
|
||||||
// const AuthForgotPassword = Loadable(lazy(() => import('pages/auth/forgot-password')));
|
|
||||||
// const AuthCheckMail = Loadable(lazy(() => import('pages/auth/check-mail')));
|
|
||||||
// const AuthResetPassword = Loadable(lazy(() => import('pages/auth/reset-password')));
|
|
||||||
// const AuthCodeVerification = Loadable(lazy(() => import('pages/auth/code-verification')));
|
|
||||||
const Login = Loadable(lazy(() => import('pages/nearle/login')));
|
const Login = Loadable(lazy(() => import('pages/nearle/login')));
|
||||||
|
|
||||||
// ==============================|| AUTH ROUTING ||============================== //
|
// ==============================|| AUTH ROUTING ||============================== //
|
||||||
@@ -21,11 +14,7 @@ const LoginRoutes = {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
element: (
|
element: <CommonLayout />,
|
||||||
// <GuestGuard>
|
|
||||||
<CommonLayout />
|
|
||||||
// </GuestGuard>
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -35,35 +24,6 @@ const LoginRoutes = {
|
|||||||
path: 'login',
|
path: 'login',
|
||||||
element: <Login />
|
element: <Login />
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
|
||||||
// path: '/',
|
|
||||||
// element: <AuthLogin />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'login',
|
|
||||||
// element: <AuthLogin />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'register',
|
|
||||||
// element: <AuthRegister />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'forgot-password',
|
|
||||||
// element: <AuthForgotPassword />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'check-mail',
|
|
||||||
// element: <AuthCheckMail />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'reset-password',
|
|
||||||
// element: <AuthResetPassword />
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// path: 'code-verification',
|
|
||||||
// element: <AuthCodeVerification />
|
|
||||||
// }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { lazy } from 'react';
|
|||||||
import MainLayout from 'layout/MainLayout';
|
import MainLayout from 'layout/MainLayout';
|
||||||
import CommonLayout from 'layout/CommonLayout';
|
import CommonLayout from 'layout/CommonLayout';
|
||||||
import Loadable from 'components/Loadable';
|
import Loadable from 'components/Loadable';
|
||||||
// import AuthGuard from 'utils/route-guard/AuthGuard';
|
|
||||||
|
|
||||||
// pages routing
|
// pages routing
|
||||||
const MaintenanceError = Loadable(lazy(() => import('pages/maintenance/404')));
|
const MaintenanceError = Loadable(lazy(() => import('pages/maintenance/404')));
|
||||||
@@ -12,10 +11,7 @@ const MaintenanceError500 = Loadable(lazy(() => import('pages/maintenance/500'))
|
|||||||
const MaintenanceUnderConstruction = Loadable(lazy(() => import('pages/maintenance/under-construction')));
|
const MaintenanceUnderConstruction = Loadable(lazy(() => import('pages/maintenance/under-construction')));
|
||||||
const MaintenanceComingSoon = Loadable(lazy(() => import('pages/maintenance/coming-soon')));
|
const MaintenanceComingSoon = Loadable(lazy(() => import('pages/maintenance/coming-soon')));
|
||||||
|
|
||||||
// render - sample page
|
|
||||||
// const SamplePage = Loadable(lazy(() => import('pages/extra-pages/sample-page')));
|
|
||||||
const Login = Loadable(lazy(() => import('pages/nearle/login1')));
|
const Login = Loadable(lazy(() => import('pages/nearle/login1')));
|
||||||
// const Dashboard = Loadable(lazy(() => import('pages/nearle/dashboard')));
|
|
||||||
|
|
||||||
const Tenants = Loadable(lazy(() => import('pages/nearle/clients/Tenants')));
|
const Tenants = Loadable(lazy(() => import('pages/nearle/clients/Tenants')));
|
||||||
const ClientsPricing = Loadable(lazy(() => import('pages/nearle/clientPricing/clientPricing')));
|
const ClientsPricing = Loadable(lazy(() => import('pages/nearle/clientPricing/clientPricing')));
|
||||||
@@ -60,11 +56,7 @@ const MainRoutes = {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
element: (
|
element: <MainLayout />,
|
||||||
// <AuthGuard>
|
|
||||||
<MainLayout />
|
|
||||||
// </AuthGuard>
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'nearle',
|
path: 'nearle',
|
||||||
@@ -188,11 +180,6 @@ const MainRoutes = {
|
|||||||
path: 'viewprofile',
|
path: 'viewprofile',
|
||||||
element: <ViewProfile />
|
element: <ViewProfile />
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
|
||||||
// path: 'orders/create',
|
|
||||||
// element: <Createorder />
|
|
||||||
// },
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,275 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Chip,
|
|
||||||
Drawer,
|
|
||||||
Grid,
|
|
||||||
InputAdornment,
|
|
||||||
List,
|
|
||||||
ListItemButton,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
OutlinedInput,
|
|
||||||
Stack,
|
|
||||||
Typography,
|
|
||||||
useMediaQuery
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import UserAvatar from './UserAvatar';
|
|
||||||
// import UserList from './UserList';
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import SimpleBar from 'components/third-party/SimpleBar';
|
|
||||||
|
|
||||||
import { ThemeMode } from 'config';
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import {
|
|
||||||
CheckCircleFilled,
|
|
||||||
ClockCircleFilled,
|
|
||||||
LogoutOutlined,
|
|
||||||
MinusCircleFilled,
|
|
||||||
RightOutlined,
|
|
||||||
SearchOutlined,
|
|
||||||
SettingOutlined
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| CHAT DRAWER ||============================== //
|
|
||||||
|
|
||||||
function ChatDrawer({ handleDrawerOpen, openChatDrawer, setUser }) {
|
|
||||||
const theme = useTheme();
|
|
||||||
const { user } = useAuth();
|
|
||||||
|
|
||||||
const matchDownLG = useMediaQuery(theme.breakpoints.down('lg'));
|
|
||||||
const drawerBG = theme.palette.mode === ThemeMode.DARK ? 'dark.main' : 'white';
|
|
||||||
|
|
||||||
// show menu to set current user status
|
|
||||||
const [anchorEl, setAnchorEl] = useState();
|
|
||||||
const handleClickRightMenu = (event) => {
|
|
||||||
setAnchorEl(event?.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCloseRightMenu = () => {
|
|
||||||
setAnchorEl(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
// set user status on status menu click
|
|
||||||
const [status, setStatus] = useState('available');
|
|
||||||
const handleRightMenuItemClick = (userStatus) => () => {
|
|
||||||
setStatus(userStatus);
|
|
||||||
handleCloseRightMenu();
|
|
||||||
};
|
|
||||||
|
|
||||||
const [search, setSearch] = useState('');
|
|
||||||
const handleSearch = async (event) => {
|
|
||||||
const newString = event?.target.value;
|
|
||||||
setSearch(newString);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Drawer
|
|
||||||
sx={{
|
|
||||||
width: 320,
|
|
||||||
flexShrink: 0,
|
|
||||||
zIndex: { xs: 1100, lg: 0 },
|
|
||||||
'& .MuiDrawer-paper': {
|
|
||||||
height: matchDownLG ? '100%' : 'auto',
|
|
||||||
width: 320,
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
position: 'relative',
|
|
||||||
border: 'none'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
variant={matchDownLG ? 'temporary' : 'persistent'}
|
|
||||||
anchor="left"
|
|
||||||
open={openChatDrawer}
|
|
||||||
ModalProps={{ keepMounted: true }}
|
|
||||||
onClose={handleDrawerOpen}
|
|
||||||
>
|
|
||||||
<MainCard
|
|
||||||
sx={{
|
|
||||||
bgcolor: matchDownLG ? 'transparent' : drawerBG,
|
|
||||||
borderRadius: '4px 0 0 4px',
|
|
||||||
borderRight: 'none'
|
|
||||||
}}
|
|
||||||
border={!matchDownLG}
|
|
||||||
content={false}
|
|
||||||
>
|
|
||||||
<Box sx={{ p: 3, pb: 1 }}>
|
|
||||||
<Stack spacing={2}>
|
|
||||||
<Stack direction="row" spacing={0.5} alignItems="center">
|
|
||||||
<Typography variant="h5" color="inherit">
|
|
||||||
Messages
|
|
||||||
</Typography>
|
|
||||||
<Chip
|
|
||||||
label="9"
|
|
||||||
component="span"
|
|
||||||
color="secondary"
|
|
||||||
sx={{
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
borderRadius: '50%',
|
|
||||||
'& .MuiChip-label': {
|
|
||||||
px: 0.5
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
id="input-search-header"
|
|
||||||
placeholder="Search"
|
|
||||||
value={search}
|
|
||||||
onChange={handleSearch}
|
|
||||||
sx={{
|
|
||||||
'& .MuiOutlinedInput-input': {
|
|
||||||
p: '10.5px 0px 12px'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
startAdornment={
|
|
||||||
<InputAdornment position="start">
|
|
||||||
<SearchOutlined style={{ fontSize: 'small' }} />
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<SimpleBar
|
|
||||||
sx={{
|
|
||||||
overflowX: 'hidden',
|
|
||||||
height: matchDownLG ? 'calc(100vh - 120px)' : 'calc(100vh - 428px)',
|
|
||||||
minHeight: matchDownLG ? 0 : 420
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box sx={{ p: 3, pt: 0 }}>
|
|
||||||
{/* <UserList setUser={setUser} search={search} /> */}
|
|
||||||
</Box>
|
|
||||||
</SimpleBar>
|
|
||||||
<Box sx={{ p: 3, pb: 0 }}>
|
|
||||||
<List component="nav">
|
|
||||||
<ListItemButton divider>
|
|
||||||
<ListItemIcon>
|
|
||||||
<LogoutOutlined />
|
|
||||||
</ListItemIcon>
|
|
||||||
|
|
||||||
<ListItemText primary="LogOut" />
|
|
||||||
</ListItemButton>
|
|
||||||
<ListItemButton divider>
|
|
||||||
<ListItemIcon>
|
|
||||||
<SettingOutlined />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary="Settings" />
|
|
||||||
</ListItemButton>
|
|
||||||
</List>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box sx={{ p: 3, pt: 1, pl: 5 }}>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={1} alignItems="center" sx={{ flexWrap: 'nowrap' }}>
|
|
||||||
<Grid item>
|
|
||||||
<UserAvatar user={{ online_status: status, avatar: 'avatar-1.png', name: 'User 1' }} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Stack sx={{ cursor: 'pointer', textDecoration: 'none' }} component={Link} to="/apps/profiles/user/personal">
|
|
||||||
<Typography align="left" variant="h5" color="textPrimary">
|
|
||||||
{user?.name}
|
|
||||||
</Typography>
|
|
||||||
<Typography align="left" variant="caption" color="textSecondary">
|
|
||||||
{user?.role}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<IconButton onClick={handleClickRightMenu} size="small" color="secondary">
|
|
||||||
<RightOutlined />
|
|
||||||
</IconButton>
|
|
||||||
<Menu
|
|
||||||
id="simple-menu"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
keepMounted
|
|
||||||
open={Boolean(anchorEl)}
|
|
||||||
onClose={handleCloseRightMenu}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: 'top',
|
|
||||||
horizontal: 'right'
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: 'bottom',
|
|
||||||
horizontal: 'right'
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
'& .MuiMenu-list': {
|
|
||||||
p: 0
|
|
||||||
},
|
|
||||||
'& .MuiMenuItem-root': {
|
|
||||||
pl: '6px',
|
|
||||||
py: '3px'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem onClick={handleRightMenuItemClick('available')}>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.success.main,
|
|
||||||
'&:hover': { color: theme.palette.success.main, bgcolor: 'transparent', transition: 'none', padding: 0 }
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CheckCircleFilled />
|
|
||||||
</IconButton>
|
|
||||||
<Typography>Active</Typography>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={handleRightMenuItemClick('offline')}>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.warning.main,
|
|
||||||
'&:hover': { color: theme.palette.warning.main, bgcolor: 'transparent', transition: 'none', padding: 0 }
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClockCircleFilled />
|
|
||||||
</IconButton>
|
|
||||||
<Typography>Away</Typography>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem onClick={handleRightMenuItemClick('do_not_disturb')}>
|
|
||||||
<IconButton
|
|
||||||
size="small"
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.grey[400],
|
|
||||||
'&:hover': { color: theme.palette.grey[400], bgcolor: 'transparent', transition: 'none', padding: 0 }
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MinusCircleFilled />
|
|
||||||
</IconButton>
|
|
||||||
<Typography>Do not disturb</Typography>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
</MainCard>
|
|
||||||
</Drawer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatDrawer.propTypes = {
|
|
||||||
handleDrawerOpen: PropTypes.func,
|
|
||||||
openChatDrawer: PropTypes.bool,
|
|
||||||
setUser: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChatDrawer;
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Card, CardContent, Grid, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import UserAvatar from './UserAvatar';
|
|
||||||
// import ChatMessageAction from './ChatMessageAction';
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import { ThemeMode } from 'config';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { EditOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| CHAT MESSAGE HISTORY ||============================== //
|
|
||||||
|
|
||||||
const ChatHistory = ({ data, theme, user }) => {
|
|
||||||
// scroll to bottom when new message is sent or received
|
|
||||||
const wrapper = useRef(document.createElement('div'));
|
|
||||||
const el = wrapper.current;
|
|
||||||
const scrollToBottom = useCallback(() => {
|
|
||||||
el.scrollIntoView(false);
|
|
||||||
}, [el]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
scrollToBottom();
|
|
||||||
}, [data.length, scrollToBottom]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid container spacing={2.5} ref={wrapper}>
|
|
||||||
{data.map((history, index) => (
|
|
||||||
<Grid item xs={12} key={index}>
|
|
||||||
{history.from !== user.name ? (
|
|
||||||
<Stack spacing={1.25} direction="row">
|
|
||||||
<Grid container spacing={1} justifyContent="flex-end">
|
|
||||||
<Grid item xs={2} md={3} xl={4} />
|
|
||||||
|
|
||||||
<Grid item xs={10} md={9} xl={8}>
|
|
||||||
<Stack direction="row" justifyContent="flex-end" alignItems="flex-start">
|
|
||||||
{/* <ChatMessageAction index={index} /> */}
|
|
||||||
<IconButton size="small" color="secondary">
|
|
||||||
<EditOutlined />
|
|
||||||
</IconButton>
|
|
||||||
<Card
|
|
||||||
sx={{
|
|
||||||
display: 'inline-block',
|
|
||||||
float: 'right',
|
|
||||||
bgcolor: theme.palette.primary.main,
|
|
||||||
boxShadow: 'none',
|
|
||||||
ml: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CardContent sx={{ p: 1, pb: '8px !important', width: 'fit-content', ml: 'auto' }}>
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography variant="h6" color={theme.palette.grey[0]} sx={{ overflowWrap: 'anywhere' }}>
|
|
||||||
{history.text}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="right" variant="subtitle2" color="textSecondary">
|
|
||||||
{history.time}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<UserAvatar user={{ online_status: 'available', avatar: 'avatar-1.png', name: 'User 1' }} />
|
|
||||||
</Stack>
|
|
||||||
) : (
|
|
||||||
<Stack direction="row" spacing={1.25} alignItems="flext-start">
|
|
||||||
<UserAvatar user={{ online_status: user.online_status, avatar: user.avatar, name: user.name }} />
|
|
||||||
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs={12} sm={7}>
|
|
||||||
<Card
|
|
||||||
sx={{
|
|
||||||
display: 'inline-block',
|
|
||||||
float: 'left',
|
|
||||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'background.background' : 'grey.0',
|
|
||||||
boxShadow: 'none'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CardContent sx={{ p: 1, pb: '8px !important' }}>
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography variant="h6" color="textPrimary" sx={{ overflowWrap: 'anywhere' }}>
|
|
||||||
{history.text}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ mt: 1 }}>
|
|
||||||
<Typography align="left" variant="subtitle2" color="textSecondary">
|
|
||||||
{history.time}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Stack>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
))}
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ChatHistory.propTypes = {
|
|
||||||
data: PropTypes.array,
|
|
||||||
theme: PropTypes.object,
|
|
||||||
user: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChatHistory;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Badge } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
// import AvatarStatus from './AvatarStatus';
|
|
||||||
import Avatar from 'components/@extended/Avatar';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
const avatarImage = require.context('assets/images/users', true);
|
|
||||||
|
|
||||||
// ==============================|| CHAT USER AVATAR WITH STATUS ICON ||============================== //
|
|
||||||
|
|
||||||
const UserAvatar = ({ user }) => (
|
|
||||||
<Badge
|
|
||||||
overlap="circular"
|
|
||||||
// badgeContent={<AvatarStatus status={user.online_status} />}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: 'top',
|
|
||||||
horizontal: 'right'
|
|
||||||
}}
|
|
||||||
sx={{ '& .MuiBox-root': { width: 6, height: 6 }, padding: 0, minWidth: 12, '& svg': { background: '#fff', borderRadius: '50%' } }}
|
|
||||||
>
|
|
||||||
<Avatar alt={user.name} src={user.avatar && avatarImage(`./${user.avatar}`)} />
|
|
||||||
</Badge>
|
|
||||||
);
|
|
||||||
|
|
||||||
UserAvatar.propTypes = {
|
|
||||||
user: PropTypes.object
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UserAvatar;
|
|
||||||
@@ -1,303 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { useMediaQuery, Box, Chip, Collapse, Divider, Grid, Stack, Switch, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
// import AvatarStatus from './AvatarStatus';
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import Avatar from 'components/@extended/Avatar';
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import SimpleBar from 'components/third-party/SimpleBar';
|
|
||||||
import { ThemeMode } from 'config';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import {
|
|
||||||
CloseOutlined,
|
|
||||||
DownOutlined,
|
|
||||||
FileDoneOutlined,
|
|
||||||
FileSyncOutlined,
|
|
||||||
FolderOpenOutlined,
|
|
||||||
LinkOutlined,
|
|
||||||
MessageOutlined,
|
|
||||||
MoreOutlined,
|
|
||||||
PhoneOutlined,
|
|
||||||
PictureOutlined,
|
|
||||||
RightOutlined,
|
|
||||||
VideoCameraOutlined
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
|
|
||||||
const avatarImage = require.context('assets/images/users', true);
|
|
||||||
|
|
||||||
// ==============================|| USER PROFILE / DETAILS ||============================== //
|
|
||||||
|
|
||||||
const UserDetails = ({ user, onClose }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const matchDownLG = useMediaQuery(theme.breakpoints.down('md'));
|
|
||||||
|
|
||||||
const [checked, setChecked] = useState(true);
|
|
||||||
if (Object.keys(user).length === 0) return <Typography>...Loading</Typography>;
|
|
||||||
|
|
||||||
let statusBGColor;
|
|
||||||
let statusColor;
|
|
||||||
if (user.online_status === 'available') {
|
|
||||||
statusBGColor = theme.palette.success.lighter;
|
|
||||||
statusColor = theme.palette.success.main;
|
|
||||||
} else if (user.online_status === 'do_not_disturb') {
|
|
||||||
statusBGColor = theme.palette.grey.A100;
|
|
||||||
statusColor = theme.palette.grey.A200;
|
|
||||||
} else {
|
|
||||||
statusBGColor = theme.palette.warning.lighter;
|
|
||||||
statusColor = theme.palette.warning.main;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MainCard
|
|
||||||
sx={{
|
|
||||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'dark.main' : 'grey.0',
|
|
||||||
borderRadius: '0 4px 4px 0',
|
|
||||||
borderLeft: 'none'
|
|
||||||
}}
|
|
||||||
content={false}
|
|
||||||
>
|
|
||||||
<Box sx={{ p: 3 }}>
|
|
||||||
{onClose && (
|
|
||||||
<IconButton size="small" sx={{ position: 'absolute', right: 8, top: 8 }} onClick={onClose} color="error">
|
|
||||||
<CloseOutlined />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
<Grid container spacing={1} justifyContent="center">
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack>
|
|
||||||
<Avatar
|
|
||||||
alt={user.name}
|
|
||||||
src={user.avatar && avatarImage(`./${user.avatar}`)}
|
|
||||||
size="xl"
|
|
||||||
sx={{
|
|
||||||
m: '8px auto',
|
|
||||||
width: 88,
|
|
||||||
height: 88,
|
|
||||||
border: '1px solid',
|
|
||||||
borderColor: theme.palette.primary.main,
|
|
||||||
p: 1,
|
|
||||||
bgcolor: 'transparent',
|
|
||||||
'& .MuiAvatar-img ': {
|
|
||||||
height: '88px',
|
|
||||||
width: '88px',
|
|
||||||
borderRadius: '50%'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography variant="h5" align="center" component="div">
|
|
||||||
{user.name}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2" align="center" color="textSecondary">
|
|
||||||
{user.role}
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
alignItems="center"
|
|
||||||
spacing={1}
|
|
||||||
justifyContent="center"
|
|
||||||
sx={{ mt: 0.75, '& .MuiChip-root': { height: '24px' } }}
|
|
||||||
>
|
|
||||||
{/* <AvatarStatus status={user?.online_status} /> */}
|
|
||||||
<Chip
|
|
||||||
label={user?.online_status.replaceAll('_', ' ')}
|
|
||||||
sx={{
|
|
||||||
bgcolor: statusBGColor,
|
|
||||||
textTransform: 'capitalize',
|
|
||||||
color: statusColor,
|
|
||||||
'& .MuiChip-label': { px: 1 }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Stack direction="row" spacing={2} justifyContent="center" sx={{ mt: 3 }}>
|
|
||||||
<IconButton size="medium" color="secondary" sx={{ boxShadow: '0px 8px 25px rgba(0, 0, 0, 0.05)' }}>
|
|
||||||
<PhoneOutlined />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton size="medium" color="secondary" sx={{ boxShadow: '0px 8px 25px rgba(0, 0, 0, 0.05)' }}>
|
|
||||||
<MessageOutlined />
|
|
||||||
</IconButton>
|
|
||||||
<IconButton size="medium" color="secondary" sx={{ boxShadow: '0px 8px 25px rgba(0, 0, 0, 0.05)' }}>
|
|
||||||
<VideoCameraOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
<Box>
|
|
||||||
<SimpleBar
|
|
||||||
sx={{
|
|
||||||
overflowX: 'hidden',
|
|
||||||
height: matchDownLG ? 'auto' : 'calc(100vh - 397px)',
|
|
||||||
minHeight: matchDownLG ? 0 : 420
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack spacing={3}>
|
|
||||||
<Stack direction="row" spacing={1.5} justifyContent="center" sx={{ px: 3 }}>
|
|
||||||
<Box sx={{ bgcolor: 'primary.lighter', p: 2, width: '50%', borderRadius: 2 }}>
|
|
||||||
<Typography color="primary">All File</Typography>
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ mt: 0.5 }}>
|
|
||||||
<FolderOpenOutlined style={{ color: theme.palette.primary.main, fontSize: '1.15em' }} />
|
|
||||||
<Typography variant="h4">231</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
<Box sx={{ bgcolor: 'secondary.lighter', p: 2, width: '50%', borderRadius: 2 }}>
|
|
||||||
<Typography>All Link</Typography>
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ mt: 0.5 }}>
|
|
||||||
<LinkOutlined style={{ fontSize: '1.15em' }} />
|
|
||||||
<Typography variant="h4">231</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
<Box sx={{ px: 3, pb: 3 }}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
alignItems="center"
|
|
||||||
justifyContent="space-between"
|
|
||||||
sx={{ cursor: 'pointer' }}
|
|
||||||
onClick={() => setChecked(!checked)}
|
|
||||||
>
|
|
||||||
<Typography variant="h5" component="div">
|
|
||||||
Information
|
|
||||||
</Typography>
|
|
||||||
<IconButton size="small" color="secondary">
|
|
||||||
<DownOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
|
||||||
<Divider />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Collapse in={checked}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" sx={{ mt: 1, mb: 2 }}>
|
|
||||||
<Typography>Address</Typography>
|
|
||||||
<Typography color="textSecondary">{user.location}</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="row" justifyContent="space-between" sx={{ mt: 2 }}>
|
|
||||||
<Typography>Email</Typography>
|
|
||||||
<Typography color="textSecondary">{user.personal_email}</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="row" justifyContent="space-between" sx={{ mt: 2 }}>
|
|
||||||
<Typography>Phone</Typography>
|
|
||||||
<Typography color="textSecondary">{user.personal_phone}</Typography>
|
|
||||||
</Stack>
|
|
||||||
<Stack direction="row" justifyContent="space-between" sx={{ mt: 2, mb: 2 }}>
|
|
||||||
<Typography>Last visited</Typography>
|
|
||||||
<Typography color="textSecondary">{user.lastMessage}</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Collapse>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
|
||||||
<Typography variant="h5">Notification</Typography>
|
|
||||||
<Switch defaultChecked />
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
|
||||||
<Divider />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
|
||||||
<Stack direction="row" alignItems="center" justifyContent="space-between">
|
|
||||||
<Typography variant="h5">File type</Typography>
|
|
||||||
<IconButton size="medium" color="secondary">
|
|
||||||
<MoreOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
|
||||||
<Divider />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1.5}>
|
|
||||||
<Avatar
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.success.dark,
|
|
||||||
bgcolor: theme.palette.success.light,
|
|
||||||
borderRadius: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FileDoneOutlined />
|
|
||||||
</Avatar>
|
|
||||||
<Stack>
|
|
||||||
<Typography>Document</Typography>
|
|
||||||
<Typography color="textSecondary">123 files, 193MB</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
<IconButton size="small" color="secondary">
|
|
||||||
<RightOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1.5}>
|
|
||||||
<Avatar
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.warning.main,
|
|
||||||
bgcolor: theme.palette.warning.lighter,
|
|
||||||
borderRadius: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PictureOutlined />
|
|
||||||
</Avatar>
|
|
||||||
<Stack>
|
|
||||||
<Typography>Photos</Typography>
|
|
||||||
<Typography color="textSecondary">53 files, 321MB</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
<IconButton size="small" color="secondary">
|
|
||||||
<RightOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
|
||||||
<Stack direction="row" alignItems="center" spacing={1.5}>
|
|
||||||
<Avatar
|
|
||||||
sx={{
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
bgcolor: theme.palette.primary.lighter,
|
|
||||||
borderRadius: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FileSyncOutlined />
|
|
||||||
</Avatar>
|
|
||||||
<Stack>
|
|
||||||
<Typography>Other</Typography>
|
|
||||||
<Typography color="textSecondary">49 files, 193MB</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Stack>
|
|
||||||
<IconButton size="small" color="secondary">
|
|
||||||
<RightOutlined />
|
|
||||||
</IconButton>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</SimpleBar>
|
|
||||||
</Box>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
UserDetails.propTypes = {
|
|
||||||
user: PropTypes.object,
|
|
||||||
onClose: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UserDetails;
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { Box } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
|
|
||||||
// ==============================|| AUTHENTICATION - CARD WRAPPER ||============================== //
|
|
||||||
|
|
||||||
const AuthCard = ({ children, ...other }) => {
|
|
||||||
const theme = useTheme();
|
|
||||||
return (
|
|
||||||
<MainCard
|
|
||||||
sx={{
|
|
||||||
maxWidth: { xs: 400, lg: 475 },
|
|
||||||
margin: { xs: 2.5, md: 3 },
|
|
||||||
'& > *': {
|
|
||||||
flexGrow: 1,
|
|
||||||
flexBasis: '50%'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
content={false}
|
|
||||||
{...other}
|
|
||||||
border={false}
|
|
||||||
boxShadow
|
|
||||||
shadow={theme.customShadows.z1}
|
|
||||||
>
|
|
||||||
<Box sx={{ p: { xs: 2, sm: 3, md: 4, xl: 5 } }}>{children}</Box>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
AuthCard.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthCard;
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Box, Grid } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import AuthFooter from 'components/cards/AuthFooter';
|
|
||||||
import Logo from 'components/logo';
|
|
||||||
import AuthCard from './AuthCard';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import AuthBackground from 'assets/images/auth/AuthBackground';
|
|
||||||
|
|
||||||
// ==============================|| AUTHENTICATION - WRAPPER ||============================== //
|
|
||||||
|
|
||||||
const AuthWrapper = ({ children }) => (
|
|
||||||
<Box sx={{ minHeight: '100vh' }}>
|
|
||||||
<AuthBackground />
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
direction="column"
|
|
||||||
justifyContent="flex-end"
|
|
||||||
sx={{
|
|
||||||
minHeight: '100vh'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid item xs={12} sx={{ ml: 3, mt: 3 }}>
|
|
||||||
<Logo />
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid
|
|
||||||
item
|
|
||||||
xs={12}
|
|
||||||
container
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
sx={{ minHeight: { xs: 'calc(100vh - 210px)', sm: 'calc(100vh - 134px)', md: 'calc(100vh - 112px)' } }}
|
|
||||||
>
|
|
||||||
<Grid item>
|
|
||||||
<AuthCard>{children}</AuthCard>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} sx={{ m: 3, mt: 1 }}>
|
|
||||||
<AuthFooter />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
|
|
||||||
AuthWrapper.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthWrapper;
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { Button, Grid, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// third-party
|
|
||||||
import OtpInput from 'react18-input-otp';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
import { ThemeMode } from 'config';
|
|
||||||
|
|
||||||
// ============================|| STATIC - CODE VERIFICATION ||============================ //
|
|
||||||
|
|
||||||
const AuthCodeVerification = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const [otp, setOtp] = useState();
|
|
||||||
|
|
||||||
const borderColor = theme.palette.mode === ThemeMode.DARK ? theme.palette.grey[200] : theme.palette.grey[300];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<OtpInput
|
|
||||||
value={otp}
|
|
||||||
onChange={(otp) => setOtp(otp)}
|
|
||||||
numInputs={4}
|
|
||||||
containerStyle={{ justifyContent: 'space-between' }}
|
|
||||||
inputStyle={{
|
|
||||||
width: '100%',
|
|
||||||
margin: '8px',
|
|
||||||
padding: '10px',
|
|
||||||
border: `1px solid ${borderColor}`,
|
|
||||||
borderRadius: 4,
|
|
||||||
':hover': {
|
|
||||||
borderColor: theme.palette.primary.main
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
focusStyle={{
|
|
||||||
outline: 'none',
|
|
||||||
boxShadow: theme.customShadows.primary,
|
|
||||||
border: `1px solid ${theme.palette.primary.main}`
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AnimateButton>
|
|
||||||
<Button disableElevation fullWidth size="large" type="submit" variant="contained">
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
</AnimateButton>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="baseline">
|
|
||||||
<Typography>Did not receive the email? Check your spam filter, or</Typography>
|
|
||||||
<Typography variant="body1" sx={{ minWidth: 85, ml: 2, textDecoration: 'none', cursor: 'pointer' }} color="primary">
|
|
||||||
Resend code
|
|
||||||
</Typography>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthCodeVerification;
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Button, FormHelperText, Grid, InputLabel, OutlinedInput, Stack, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// third party
|
|
||||||
import * as Yup from 'yup';
|
|
||||||
import { Formik } from 'formik';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
import useScriptRef from 'hooks/useScriptRef';
|
|
||||||
import { dispatch } from 'store';
|
|
||||||
import { openSnackbar } from 'store/reducers/snackbar';
|
|
||||||
|
|
||||||
// ============================|| FIREBASE - FORGOT PASSWORD ||============================ //
|
|
||||||
|
|
||||||
const AuthForgotPassword = () => {
|
|
||||||
const scriptedRef = useScriptRef();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const { isLoggedIn, resetPassword } = useAuth();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
email: '',
|
|
||||||
submit: null
|
|
||||||
}}
|
|
||||||
validationSchema={Yup.object().shape({
|
|
||||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required')
|
|
||||||
})}
|
|
||||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
|
||||||
try {
|
|
||||||
await resetPassword(values.email).then(
|
|
||||||
() => {
|
|
||||||
setStatus({ success: true });
|
|
||||||
setSubmitting(false);
|
|
||||||
dispatch(
|
|
||||||
openSnackbar({
|
|
||||||
open: true,
|
|
||||||
message: 'Check mail for reset password link',
|
|
||||||
variant: 'alert',
|
|
||||||
alert: {
|
|
||||||
color: 'success'
|
|
||||||
},
|
|
||||||
close: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate(isLoggedIn ? '/auth/check-mail' : '/check-mail', { replace: true });
|
|
||||||
}, 1500);
|
|
||||||
|
|
||||||
// WARNING: do not set any formik state here as formik might be already destroyed here. You may get following error by doing so.
|
|
||||||
// Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application.
|
|
||||||
// To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
|
|
||||||
// github issue: https://github.com/formium/formik/issues/2430
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
setStatus({ success: false });
|
|
||||||
setErrors({ submit: err.message });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: false });
|
|
||||||
setErrors({ submit: err.message });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
|
||||||
<form noValidate onSubmit={handleSubmit}>
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="email-forgot">Email Address</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.email && errors.email)}
|
|
||||||
id="email-forgot"
|
|
||||||
type="email"
|
|
||||||
value={values.email}
|
|
||||||
name="email"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="Enter email address"
|
|
||||||
inputProps={{}}
|
|
||||||
/>
|
|
||||||
{touched.email && errors.email && (
|
|
||||||
<FormHelperText error id="helper-text-email-forgot">
|
|
||||||
{errors.email}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
{errors.submit && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
<Grid item xs={12} sx={{ mb: -2 }}>
|
|
||||||
<Typography variant="caption">Do not forgot to check SPAM box.</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AnimateButton>
|
|
||||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
|
||||||
Send Password Reset Email
|
|
||||||
</Button>
|
|
||||||
</AnimateButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthForgotPassword;
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Checkbox,
|
|
||||||
FormControlLabel,
|
|
||||||
FormHelperText,
|
|
||||||
Grid,
|
|
||||||
Link,
|
|
||||||
InputAdornment,
|
|
||||||
InputLabel,
|
|
||||||
OutlinedInput,
|
|
||||||
Stack,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
// third party
|
|
||||||
import * as Yup from 'yup';
|
|
||||||
import { Formik } from 'formik';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
import useScriptRef from 'hooks/useScriptRef';
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ============================|| JWT - LOGIN ||============================ //
|
|
||||||
|
|
||||||
const AuthLogin = () => {
|
|
||||||
const [checked, setChecked] = React.useState(false);
|
|
||||||
|
|
||||||
const { login } = useAuth();
|
|
||||||
const scriptedRef = useScriptRef();
|
|
||||||
|
|
||||||
const [showPassword, setShowPassword] = React.useState(false);
|
|
||||||
const handleClickShowPassword = () => {
|
|
||||||
setShowPassword(!showPassword);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMouseDownPassword = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
email: 'info@codedthemes.com',
|
|
||||||
password: '123456',
|
|
||||||
submit: null
|
|
||||||
}}
|
|
||||||
validationSchema={Yup.object().shape({
|
|
||||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
|
|
||||||
password: Yup.string().max(255).required('Password is required')
|
|
||||||
})}
|
|
||||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
|
||||||
try {
|
|
||||||
await login(values.email, values.password);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: true });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: false });
|
|
||||||
setErrors({ submit: err.message });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
|
||||||
<form noValidate onSubmit={handleSubmit}>
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="email-login">Email Address</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
id="email-login"
|
|
||||||
type="email"
|
|
||||||
value={values.email}
|
|
||||||
name="email"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="Enter email address"
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.email && errors.email)}
|
|
||||||
/>
|
|
||||||
{touched.email && errors.email && (
|
|
||||||
<FormHelperText error id="standard-weight-helper-text-email-login">
|
|
||||||
{errors.email}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="password-login">Password</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.password && errors.password)}
|
|
||||||
id="-password-login"
|
|
||||||
type={showPassword ? 'text' : 'password'}
|
|
||||||
value={values.password}
|
|
||||||
name="password"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
endAdornment={
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<IconButton
|
|
||||||
aria-label="toggle password visibility"
|
|
||||||
onClick={handleClickShowPassword}
|
|
||||||
onMouseDown={handleMouseDownPassword}
|
|
||||||
edge="end"
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
|
||||||
</IconButton>
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
placeholder="Enter password"
|
|
||||||
/>
|
|
||||||
{touched.password && errors.password && (
|
|
||||||
<FormHelperText error id="standard-weight-helper-text-password-login">
|
|
||||||
{errors.password}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<Grid item xs={12} sx={{ mt: -1 }}>
|
|
||||||
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={checked}
|
|
||||||
onChange={(event) => setChecked(event.target.checked)}
|
|
||||||
name="checked"
|
|
||||||
color="primary"
|
|
||||||
size="small"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={<Typography variant="h6">Keep me sign in</Typography>}
|
|
||||||
/>
|
|
||||||
<Link variant="h6" component={RouterLink} to="/forgot-password" color="text.primary">
|
|
||||||
Forgot Password?
|
|
||||||
</Link>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
{errors.submit && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AnimateButton>
|
|
||||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
|
||||||
Login
|
|
||||||
</Button>
|
|
||||||
</AnimateButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthLogin;
|
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { Link as RouterLink, useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
FormControl,
|
|
||||||
FormHelperText,
|
|
||||||
Grid,
|
|
||||||
Link,
|
|
||||||
InputAdornment,
|
|
||||||
InputLabel,
|
|
||||||
OutlinedInput,
|
|
||||||
Stack,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
// third party
|
|
||||||
import * as Yup from 'yup';
|
|
||||||
import { Formik } from 'formik';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
import useScriptRef from 'hooks/useScriptRef';
|
|
||||||
import { dispatch } from 'store';
|
|
||||||
import { openSnackbar } from 'store/reducers/snackbar';
|
|
||||||
import { strengthColor, strengthIndicator } from 'utils/password-strength';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ============================|| JWT - REGISTER ||============================ //
|
|
||||||
|
|
||||||
const AuthRegister = () => {
|
|
||||||
const { register } = useAuth();
|
|
||||||
const scriptedRef = useScriptRef();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const [level, setLevel] = useState();
|
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
|
||||||
const handleClickShowPassword = () => {
|
|
||||||
setShowPassword(!showPassword);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMouseDownPassword = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
const changePassword = (value) => {
|
|
||||||
const temp = strengthIndicator(value);
|
|
||||||
setLevel(strengthColor(temp));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
changePassword('');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
firstname: '',
|
|
||||||
lastname: '',
|
|
||||||
email: '',
|
|
||||||
company: '',
|
|
||||||
password: '',
|
|
||||||
submit: null
|
|
||||||
}}
|
|
||||||
validationSchema={Yup.object().shape({
|
|
||||||
firstname: Yup.string().max(255).required('First Name is required'),
|
|
||||||
lastname: Yup.string().max(255).required('Last Name is required'),
|
|
||||||
email: Yup.string().email('Must be a valid email').max(255).required('Email is required'),
|
|
||||||
password: Yup.string().max(255).required('Password is required')
|
|
||||||
})}
|
|
||||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
|
||||||
try {
|
|
||||||
await register(values.email, values.password, values.firstname, values.lastname);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: true });
|
|
||||||
setSubmitting(false);
|
|
||||||
dispatch(
|
|
||||||
openSnackbar({
|
|
||||||
open: true,
|
|
||||||
message: 'Your registration has been successfully completed.',
|
|
||||||
variant: 'alert',
|
|
||||||
alert: {
|
|
||||||
color: 'success'
|
|
||||||
},
|
|
||||||
close: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate('/login', { replace: true });
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: false });
|
|
||||||
setErrors({ submit: err.message });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
|
||||||
<form noValidate onSubmit={handleSubmit}>
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="firstname-signup">First Name*</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
id="firstname-login"
|
|
||||||
type="firstname"
|
|
||||||
value={values.firstname}
|
|
||||||
name="firstname"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="John"
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.firstname && errors.firstname)}
|
|
||||||
/>
|
|
||||||
{touched.firstname && errors.firstname && (
|
|
||||||
<FormHelperText error id="helper-text-firstname-signup">
|
|
||||||
{errors.firstname}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="lastname-signup">Last Name*</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.lastname && errors.lastname)}
|
|
||||||
id="lastname-signup"
|
|
||||||
type="lastname"
|
|
||||||
value={values.lastname}
|
|
||||||
name="lastname"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="Doe"
|
|
||||||
inputProps={{}}
|
|
||||||
/>
|
|
||||||
{touched.lastname && errors.lastname && (
|
|
||||||
<FormHelperText error id="helper-text-lastname-signup">
|
|
||||||
{errors.lastname}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="company-signup">Company</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.company && errors.company)}
|
|
||||||
id="company-signup"
|
|
||||||
value={values.company}
|
|
||||||
name="company"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="Demo Inc."
|
|
||||||
inputProps={{}}
|
|
||||||
/>
|
|
||||||
{touched.company && errors.company && (
|
|
||||||
<FormHelperText error id="helper-text-company-signup">
|
|
||||||
{errors.company}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="email-signup">Email Address*</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.email && errors.email)}
|
|
||||||
id="email-login"
|
|
||||||
type="email"
|
|
||||||
value={values.email}
|
|
||||||
name="email"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="demo@company.com"
|
|
||||||
inputProps={{}}
|
|
||||||
/>
|
|
||||||
{touched.email && errors.email && (
|
|
||||||
<FormHelperText error id="helper-text-email-signup">
|
|
||||||
{errors.email}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="password-signup">Password</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.password && errors.password)}
|
|
||||||
id="password-signup"
|
|
||||||
type={showPassword ? 'text' : 'password'}
|
|
||||||
value={values.password}
|
|
||||||
name="password"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={(e) => {
|
|
||||||
handleChange(e);
|
|
||||||
changePassword(e.target.value);
|
|
||||||
}}
|
|
||||||
endAdornment={
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<IconButton
|
|
||||||
aria-label="toggle password visibility"
|
|
||||||
onClick={handleClickShowPassword}
|
|
||||||
onMouseDown={handleMouseDownPassword}
|
|
||||||
edge="end"
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
|
||||||
</IconButton>
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
placeholder="******"
|
|
||||||
inputProps={{}}
|
|
||||||
/>
|
|
||||||
{touched.password && errors.password && (
|
|
||||||
<FormHelperText error id="helper-text-password-signup">
|
|
||||||
{errors.password}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
<FormControl fullWidth sx={{ mt: 2 }}>
|
|
||||||
<Grid container spacing={2} alignItems="center">
|
|
||||||
<Grid item>
|
|
||||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Typography variant="subtitle1" fontSize="0.75rem">
|
|
||||||
{level?.label}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography variant="body2">
|
|
||||||
By Signing up, you agree to our
|
|
||||||
<Link variant="subtitle2" component={RouterLink} to="#">
|
|
||||||
Terms of Service
|
|
||||||
</Link>
|
|
||||||
and
|
|
||||||
<Link variant="subtitle2" component={RouterLink} to="#">
|
|
||||||
Privacy Policy
|
|
||||||
</Link>
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
{errors.submit && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AnimateButton>
|
|
||||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
|
||||||
Create Account
|
|
||||||
</Button>
|
|
||||||
</AnimateButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthRegister;
|
|
||||||
@@ -1,201 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
FormControl,
|
|
||||||
FormHelperText,
|
|
||||||
Grid,
|
|
||||||
InputAdornment,
|
|
||||||
InputLabel,
|
|
||||||
OutlinedInput,
|
|
||||||
Stack,
|
|
||||||
Typography
|
|
||||||
} from '@mui/material';
|
|
||||||
|
|
||||||
// third party
|
|
||||||
import * as Yup from 'yup';
|
|
||||||
import { Formik } from 'formik';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import IconButton from 'components/@extended/IconButton';
|
|
||||||
import AnimateButton from 'components/@extended/AnimateButton';
|
|
||||||
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
import useScriptRef from 'hooks/useScriptRef';
|
|
||||||
import { dispatch } from 'store';
|
|
||||||
import { openSnackbar } from 'store/reducers/snackbar';
|
|
||||||
import { strengthColor, strengthIndicator } from 'utils/password-strength';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ============================|| STATIC - RESET PASSWORD ||============================ //
|
|
||||||
|
|
||||||
const AuthResetPassword = () => {
|
|
||||||
const scriptedRef = useScriptRef();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
const { isLoggedIn } = useAuth();
|
|
||||||
|
|
||||||
const [level, setLevel] = useState();
|
|
||||||
const [showPassword, setShowPassword] = useState(false);
|
|
||||||
const handleClickShowPassword = () => {
|
|
||||||
setShowPassword(!showPassword);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMouseDownPassword = (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
};
|
|
||||||
|
|
||||||
const changePassword = (value) => {
|
|
||||||
const temp = strengthIndicator(value);
|
|
||||||
setLevel(strengthColor(temp));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
changePassword('');
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
password: '',
|
|
||||||
confirmPassword: '',
|
|
||||||
submit: null
|
|
||||||
}}
|
|
||||||
validationSchema={Yup.object().shape({
|
|
||||||
password: Yup.string().max(255).required('Password is required'),
|
|
||||||
confirmPassword: Yup.string()
|
|
||||||
.required('Confirm Password is required')
|
|
||||||
.test('confirmPassword', 'Both Password must be match!', (confirmPassword, yup) => yup.parent.password === confirmPassword)
|
|
||||||
})}
|
|
||||||
onSubmit={async (values, { setErrors, setStatus, setSubmitting }) => {
|
|
||||||
try {
|
|
||||||
// password reset
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: true });
|
|
||||||
setSubmitting(false);
|
|
||||||
|
|
||||||
dispatch(
|
|
||||||
openSnackbar({
|
|
||||||
open: true,
|
|
||||||
message: 'Successfuly reset password.',
|
|
||||||
variant: 'alert',
|
|
||||||
alert: {
|
|
||||||
color: 'success'
|
|
||||||
},
|
|
||||||
close: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate(isLoggedIn ? '/auth/login' : '/login', { replace: true });
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (scriptedRef.current) {
|
|
||||||
setStatus({ success: false });
|
|
||||||
setErrors({ submit: err.message });
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ errors, handleBlur, handleChange, handleSubmit, isSubmitting, touched, values }) => (
|
|
||||||
<form noValidate onSubmit={handleSubmit}>
|
|
||||||
<Grid container spacing={3}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="password-reset">Password</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.password && errors.password)}
|
|
||||||
id="password-reset"
|
|
||||||
type={showPassword ? 'text' : 'password'}
|
|
||||||
value={values.password}
|
|
||||||
name="password"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={(e) => {
|
|
||||||
handleChange(e);
|
|
||||||
changePassword(e.target.value);
|
|
||||||
}}
|
|
||||||
endAdornment={
|
|
||||||
<InputAdornment position="end">
|
|
||||||
<IconButton
|
|
||||||
aria-label="toggle password visibility"
|
|
||||||
onClick={handleClickShowPassword}
|
|
||||||
onMouseDown={handleMouseDownPassword}
|
|
||||||
edge="end"
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />}
|
|
||||||
</IconButton>
|
|
||||||
</InputAdornment>
|
|
||||||
}
|
|
||||||
placeholder="Enter password"
|
|
||||||
/>
|
|
||||||
{touched.password && errors.password && (
|
|
||||||
<FormHelperText error id="helper-text-password-reset">
|
|
||||||
{errors.password}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
<FormControl fullWidth sx={{ mt: 2 }}>
|
|
||||||
<Grid container spacing={2} alignItems="center">
|
|
||||||
<Grid item>
|
|
||||||
<Box sx={{ bgcolor: level?.color, width: 85, height: 8, borderRadius: '7px' }} />
|
|
||||||
</Grid>
|
|
||||||
<Grid item>
|
|
||||||
<Typography variant="subtitle1" fontSize="0.75rem">
|
|
||||||
{level?.label}
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Stack spacing={1}>
|
|
||||||
<InputLabel htmlFor="confirm-password-reset">Confirm Password</InputLabel>
|
|
||||||
<OutlinedInput
|
|
||||||
fullWidth
|
|
||||||
error={Boolean(touched.confirmPassword && errors.confirmPassword)}
|
|
||||||
id="confirm-password-reset"
|
|
||||||
type="password"
|
|
||||||
value={values.confirmPassword}
|
|
||||||
name="confirmPassword"
|
|
||||||
onBlur={handleBlur}
|
|
||||||
onChange={handleChange}
|
|
||||||
placeholder="Enter confirm password"
|
|
||||||
/>
|
|
||||||
{touched.confirmPassword && errors.confirmPassword && (
|
|
||||||
<FormHelperText error id="helper-text-confirm-password-reset">
|
|
||||||
{errors.confirmPassword}
|
|
||||||
</FormHelperText>
|
|
||||||
)}
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{errors.submit && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<FormHelperText error>{errors.submit}</FormHelperText>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AnimateButton>
|
|
||||||
<Button disableElevation disabled={isSubmitting} fullWidth size="large" type="submit" variant="contained" color="primary">
|
|
||||||
Reset Password
|
|
||||||
</Button>
|
|
||||||
</AnimateButton>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthResetPassword;
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
// material-ui
|
|
||||||
import { useTheme } from '@mui/material/styles';
|
|
||||||
import { useMediaQuery, Button, Stack } from '@mui/material';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import Google from 'assets/images/icons/google.svg';
|
|
||||||
import Twitter from 'assets/images/icons/twitter.svg';
|
|
||||||
import Facebook from 'assets/images/icons/facebook.svg';
|
|
||||||
|
|
||||||
// ==============================|| FIREBASE - SOCIAL BUTTON ||============================== //
|
|
||||||
|
|
||||||
const FirebaseSocial = () => {
|
|
||||||
const theme = useTheme();
|
|
||||||
const matchDownSM = useMediaQuery(theme.breakpoints.down('sm'));
|
|
||||||
|
|
||||||
const { firebaseFacebookSignIn, firebaseGoogleSignIn, firebaseTwitterSignIn } = useAuth();
|
|
||||||
const googleHandler = async () => {
|
|
||||||
try {
|
|
||||||
await firebaseGoogleSignIn();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const twitterHandler = async () => {
|
|
||||||
try {
|
|
||||||
await firebaseTwitterSignIn();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const facebookHandler = async () => {
|
|
||||||
try {
|
|
||||||
await firebaseFacebookSignIn();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Stack
|
|
||||||
direction="row"
|
|
||||||
spacing={matchDownSM ? 1 : 2}
|
|
||||||
justifyContent={matchDownSM ? 'space-around' : 'space-between'}
|
|
||||||
sx={{ '& .MuiButton-startIcon': { mr: matchDownSM ? 0 : 1, ml: matchDownSM ? 0 : -0.5 } }}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
color="secondary"
|
|
||||||
fullWidth={!matchDownSM}
|
|
||||||
startIcon={<img src={Google} alt="Google" />}
|
|
||||||
onClick={googleHandler}
|
|
||||||
>
|
|
||||||
{!matchDownSM && 'Google'}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
color="secondary"
|
|
||||||
fullWidth={!matchDownSM}
|
|
||||||
startIcon={<img src={Twitter} alt="Twitter" />}
|
|
||||||
onClick={twitterHandler}
|
|
||||||
>
|
|
||||||
{!matchDownSM && 'Twitter'}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
color="secondary"
|
|
||||||
fullWidth={!matchDownSM}
|
|
||||||
startIcon={<img src={Facebook} alt="Facebook" />}
|
|
||||||
onClick={facebookHandler}
|
|
||||||
>
|
|
||||||
{!matchDownSM && 'Facebook'}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default FirebaseSocial;
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import { Link as RouterLink } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { Link, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
|
|
||||||
// table data
|
|
||||||
function createData(name, designation, product, date, badgeText, badgeType) {
|
|
||||||
return { name, designation, product, date, badgeText, badgeType };
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows = [
|
|
||||||
createData('Materially', 'Powerful Admin Theme', '16,300', '$53', '$15,652'),
|
|
||||||
createData('Photoshop', 'Design Software', '26,421', '$35', '$8,785'),
|
|
||||||
createData('Guruable', 'Best Admin Template', '8,265', '$98', '$9,652'),
|
|
||||||
createData('Flatable', 'Admin App', '10,652', '$20', '$7,856')
|
|
||||||
];
|
|
||||||
// =========================|| DATA WIDGET - APPLICATION SALES ||========================= //
|
|
||||||
|
|
||||||
const ApplicationSales = () => (
|
|
||||||
<MainCard
|
|
||||||
title="Application Sales"
|
|
||||||
content={false}
|
|
||||||
secondary={
|
|
||||||
<Link component={RouterLink} to="#" color="primary">
|
|
||||||
View all
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TableContainer>
|
|
||||||
<Table>
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
<TableCell sx={{ pl: 3 }}>Application</TableCell>
|
|
||||||
<TableCell align="right">Sales</TableCell>
|
|
||||||
<TableCell align="right">Avg. Price</TableCell>
|
|
||||||
<TableCell align="right" sx={{ pr: 3 }}>
|
|
||||||
Total
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{rows.map((row, index) => (
|
|
||||||
<TableRow hover key={index}>
|
|
||||||
{/* <TableCell sx={{ pl: 3 }}>
|
|
||||||
<Typography align="left" variant="subtitle1">
|
|
||||||
{row.name}
|
|
||||||
</Typography>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
{row.designation}
|
|
||||||
</Typography>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell align="right">{row.product}</TableCell>
|
|
||||||
<TableCell align="right">{row.date}</TableCell>
|
|
||||||
<TableCell align="right" sx={{ pr: 3 }}>
|
|
||||||
<span>{row.badgeText}</span>
|
|
||||||
</TableCell> */}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default ApplicationSales;
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
import { Link as RouterLink } from 'react-router-dom';
|
|
||||||
|
|
||||||
// material-ui
|
|
||||||
import { CardContent, Grid, Link, Typography } from '@mui/material';
|
|
||||||
|
|
||||||
// project imports
|
|
||||||
import MainCard from 'components/MainCard';
|
|
||||||
import Avatar from 'components/@extended/Avatar';
|
|
||||||
|
|
||||||
// assets
|
|
||||||
import { TwitterCircleFilled, ClockCircleFilled, BugFilled, MobileFilled, WarningFilled } from '@ant-design/icons';
|
|
||||||
|
|
||||||
// ==============================|| DATA WIDGET - TASKS CARD ||============================== //
|
|
||||||
|
|
||||||
const TasksCard = () => (
|
|
||||||
<MainCard
|
|
||||||
title="Tasks"
|
|
||||||
content={false}
|
|
||||||
secondary={
|
|
||||||
<Link component={RouterLink} to="#" color="primary">
|
|
||||||
View all
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<CardContent>
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
spacing={2.75}
|
|
||||||
alignItems="center"
|
|
||||||
sx={{
|
|
||||||
position: 'relative',
|
|
||||||
'&>*': {
|
|
||||||
position: 'relative',
|
|
||||||
zIndex: '5'
|
|
||||||
},
|
|
||||||
'&:after': {
|
|
||||||
content: '""',
|
|
||||||
position: 'absolute',
|
|
||||||
top: 10,
|
|
||||||
left: 38,
|
|
||||||
width: 2,
|
|
||||||
height: '100%',
|
|
||||||
background: '#ebebeb',
|
|
||||||
zIndex: '1'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item>
|
|
||||||
<Avatar type="filled" color="success" size="sm" sx={{ top: 10 }}>
|
|
||||||
<TwitterCircleFilled />
|
|
||||||
</Avatar>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Grid container spacing={0}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
8:50
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="body2">
|
|
||||||
You’re getting more and more followers, keep it up!
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item>
|
|
||||||
<Avatar type="filled" color="primary" size="sm" sx={{ top: 10 }}>
|
|
||||||
<ClockCircleFilled />
|
|
||||||
</Avatar>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Grid container spacing={0}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
Sat, 5 Mar
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="body2">
|
|
||||||
Design mobile Application
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item>
|
|
||||||
<Avatar type="filled" color="error" size="sm" sx={{ top: 10 }}>
|
|
||||||
<BugFilled />
|
|
||||||
</Avatar>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Grid container spacing={0}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
Sun, 17 Feb
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="body2">
|
|
||||||
<Link component={RouterLink} to="#" underline="hover">
|
|
||||||
Jenny
|
|
||||||
</Link>{' '}
|
|
||||||
assign you a task{' '}
|
|
||||||
<Link component={RouterLink} to="#" underline="hover">
|
|
||||||
Mockup Design
|
|
||||||
</Link>
|
|
||||||
.
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item>
|
|
||||||
<Avatar type="filled" color="warning" size="sm" sx={{ top: 10 }}>
|
|
||||||
<WarningFilled />
|
|
||||||
</Avatar>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Grid container spacing={0}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
Sat, 18 Mar
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="body2">
|
|
||||||
Design logo
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item>
|
|
||||||
<Avatar type="filled" color="success" size="sm" sx={{ top: 10 }}>
|
|
||||||
<MobileFilled />
|
|
||||||
</Avatar>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs zeroMinWidth>
|
|
||||||
<Grid container spacing={0}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="caption" color="secondary">
|
|
||||||
Sat, 22 Mar
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<Typography align="left" variant="body2">
|
|
||||||
Design mobile Application
|
|
||||||
</Typography>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</CardContent>
|
|
||||||
</MainCard>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default TasksCard;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
* Password validator for login pages
|
|
||||||
*/
|
|
||||||
|
|
||||||
// has number
|
|
||||||
const hasNumber = (number) => new RegExp(/[0-9]/).test(number);
|
|
||||||
|
|
||||||
// has mix of small and capitals
|
|
||||||
const hasMixed = (number) => new RegExp(/[a-z]/).test(number) && new RegExp(/[A-Z]/).test(number);
|
|
||||||
|
|
||||||
// has special chars
|
|
||||||
const hasSpecial = (number) => new RegExp(/[!#@$%^&*)(+=._-]/).test(number);
|
|
||||||
|
|
||||||
// set color based on password strength
|
|
||||||
export const strengthColor = (count) => {
|
|
||||||
if (count < 2) return { label: 'Poor', color: 'error.main' };
|
|
||||||
if (count < 3) return { label: 'Weak', color: 'warning.main' };
|
|
||||||
if (count < 4) return { label: 'Normal', color: 'warning.dark' };
|
|
||||||
if (count < 5) return { label: 'Good', color: 'success.main' };
|
|
||||||
if (count < 6) return { label: 'Strong', color: 'success.dark' };
|
|
||||||
return { label: 'Poor', color: 'error.main' };
|
|
||||||
};
|
|
||||||
|
|
||||||
// password strength indicator
|
|
||||||
export const strengthIndicator = (number) => {
|
|
||||||
let strengths = 0;
|
|
||||||
if (number.length > 5) strengths += 1;
|
|
||||||
if (number.length > 7) strengths += 1;
|
|
||||||
if (hasNumber(number)) strengths += 1;
|
|
||||||
if (hasSpecial(number)) strengths += 1;
|
|
||||||
if (hasMixed(number)) strengths += 1;
|
|
||||||
return strengths;
|
|
||||||
};
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
function isNumber(value) {
|
|
||||||
return new RegExp('^(?=.*[0-9]).+$').test(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLowercaseChar(value) {
|
|
||||||
return new RegExp('^(?=.*[a-z]).+$').test(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUppercaseChar(value) {
|
|
||||||
return new RegExp('^(?=.*[A-Z]).+$').test(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSpecialChar(value) {
|
|
||||||
return new RegExp('^(?=.*[-+_!@#$%^&*.,?]).+$').test(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function minLength(value) {
|
|
||||||
return value.length > 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { isNumber, isLowercaseChar, isUppercaseChar, isSpecialChar, minLength };
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
|
|
||||||
// ==============================|| AUTH GUARD ||============================== //
|
|
||||||
|
|
||||||
const AuthGuard = ({ children }) => {
|
|
||||||
const { isLoggedIn } = useAuth();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isLoggedIn) {
|
|
||||||
navigate('login', {
|
|
||||||
state: {
|
|
||||||
from: location.pathname
|
|
||||||
},
|
|
||||||
replace: true
|
|
||||||
});
|
|
||||||
navigate('login', { replace: true });
|
|
||||||
}
|
|
||||||
}, [isLoggedIn, navigate, location]);
|
|
||||||
|
|
||||||
return children;
|
|
||||||
};
|
|
||||||
|
|
||||||
AuthGuard.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthGuard;
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
// project import
|
|
||||||
import { APP_DEFAULT_PATH } from 'config';
|
|
||||||
import useAuth from 'hooks/useAuth';
|
|
||||||
|
|
||||||
// ==============================|| GUEST GUARD ||============================== //
|
|
||||||
|
|
||||||
const GuestGuard = ({ children }) => {
|
|
||||||
const { isLoggedIn } = useAuth();
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isLoggedIn) {
|
|
||||||
navigate(location?.state?.from ? location?.state?.from : APP_DEFAULT_PATH, {
|
|
||||||
state: {
|
|
||||||
from: ''
|
|
||||||
},
|
|
||||||
replace: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [isLoggedIn, navigate, location]);
|
|
||||||
|
|
||||||
return children;
|
|
||||||
};
|
|
||||||
|
|
||||||
GuestGuard.propTypes = {
|
|
||||||
children: PropTypes.node
|
|
||||||
};
|
|
||||||
|
|
||||||
export default GuestGuard;
|
|
||||||
Reference in New Issue
Block a user