manager modal changes, dashboard apis implemented and add dashboard page for user created
This commit is contained in:
parent
7f4914c695
commit
99e3f8c9f9
|
@ -57,9 +57,9 @@ export default function AddManagerModal({ open, handleClose }) {
|
|||
try {
|
||||
await dispatch(addManager(managerData));
|
||||
dispatch(managerList());
|
||||
clearErrors();
|
||||
reset();
|
||||
handleClose();
|
||||
clearErrors();
|
||||
reset();
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
console.error("Error adding manager:", error);
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ export default function AddManagerModal({ open, handleClose }) {
|
|||
|
||||
// Handle modal close, clearing errors and resetting form
|
||||
const handleModalClose = () => {
|
||||
clearErrors();
|
||||
reset();
|
||||
clearErrors();
|
||||
reset();
|
||||
handleClose();
|
||||
};
|
||||
|
||||
|
@ -348,6 +348,9 @@ export default function AddManagerModal({ open, handleClose }) {
|
|||
togglePasswordVisibility
|
||||
}
|
||||
edge="end"
|
||||
sx={{
|
||||
color: "#000000",
|
||||
}}
|
||||
>
|
||||
{showPassword ? (
|
||||
<VisibilityOff />
|
||||
|
|
105
src/components/MainGrid/adminGrid.tsx
Normal file
105
src/components/MainGrid/adminGrid.tsx
Normal file
|
@ -0,0 +1,105 @@
|
|||
import React, { useEffect } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import SessionsChart from "../SessionsChart/sessionChart";
|
||||
import ResourcesPieChart from "../ResourcePieChart/resourcePieChart";
|
||||
import RoundedBarChart from "../barChartCard/barChartCard";
|
||||
import LineChartCard from "../LineChartCard/lineChartCard";
|
||||
import { AppDispatch, RootState } from "../../redux/store/store";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
|
||||
import AppTheme from "../../shared-theme/AppTheme";
|
||||
import StatCard from "../StatCard/statCard";
|
||||
|
||||
export default function AdminGrid() {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const { totalManagers, totalUsers, totalStations, loading, error } =
|
||||
useSelector((state: RootState) => state.dashboardReducer);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchDashboardData());
|
||||
}, [dispatch]);
|
||||
|
||||
// Fallback defaults if data is undefined
|
||||
const data = {
|
||||
totalManagers: totalManagers ?? 12,
|
||||
totalUsers: totalUsers ?? 24,
|
||||
totalStations: totalStations ?? 8,
|
||||
};
|
||||
|
||||
const statCards = [
|
||||
{ title: "Total Managers", value: data.totalManagers },
|
||||
{ title: "Total Users", value: data.totalUsers },
|
||||
{ title: "Total Stations", value: data.totalStations },
|
||||
];
|
||||
|
||||
return (
|
||||
<AppTheme>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
maxWidth: "1800px",
|
||||
mx: "auto",
|
||||
px: { xs: 2, sm: 1, md: 0 },
|
||||
background: (theme) => theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
{/* Header */}
|
||||
<Typography variant="h4" component="h2" sx={{ mb: 3 }}>
|
||||
Admin Dashboard
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={3} justifyContent="center">
|
||||
{statCards.map((card, index) => (
|
||||
<Grid
|
||||
key={index}
|
||||
item
|
||||
xs={12}
|
||||
sm={6}
|
||||
md={
|
||||
statCards.length === 1
|
||||
? 12
|
||||
: statCards.length === 2
|
||||
? 6
|
||||
: 4
|
||||
}
|
||||
lg={
|
||||
statCards.length === 1
|
||||
? 12
|
||||
: statCards.length === 2
|
||||
? 6
|
||||
: 4
|
||||
}
|
||||
xl={
|
||||
statCards.length === 1
|
||||
? 8
|
||||
: statCards.length === 2
|
||||
? 6
|
||||
: 4
|
||||
}
|
||||
>
|
||||
<StatCard {...card} />
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
{/* Charts */}
|
||||
<Grid container spacing={3} sx={{ mt: 1 }}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<SessionsChart />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<ResourcesPieChart />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<RoundedBarChart />
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<LineChartCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</AppTheme>
|
||||
);
|
||||
}
|
|
@ -1,3 +1,120 @@
|
|||
// import React, { useEffect } from "react";
|
||||
// import Grid from "@mui/material/Grid";
|
||||
// import Box from "@mui/material/Box";
|
||||
// import Typography from "@mui/material/Typography";
|
||||
// import SessionsChart from "../SessionsChart/sessionChart";
|
||||
// import ResourcesPieChart from "../ResourcePieChart/resourcePieChart";
|
||||
// import RoundedBarChart from "../barChartCard/barChartCard";
|
||||
// import LineChartCard from "../LineChartCard/lineChartCard";
|
||||
// import { AppDispatch, RootState } from "../../redux/store/store";
|
||||
// import { useDispatch, useSelector } from "react-redux";
|
||||
// import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
|
||||
// import AppTheme from "../../shared-theme/AppTheme"; // Import the custom theme
|
||||
// import StatCard from "../StatCard/statCard"; // Adjusted import for consistency
|
||||
|
||||
// export default function MainGrid() {
|
||||
// const dispatch = useDispatch<AppDispatch>();
|
||||
// const {
|
||||
// totalAdmins,
|
||||
// totalManagers,
|
||||
// totalUsers,
|
||||
// totalStations,
|
||||
|
||||
// } = useSelector((state: RootState) => state.dashboardReducer);
|
||||
// const userType = useSelector(
|
||||
// (state: RootState) => state.profileReducer.user?.userType
|
||||
// );
|
||||
// useEffect(() => {
|
||||
// dispatch(fetchDashboardData());
|
||||
// }, [dispatch]);
|
||||
|
||||
// const data = {
|
||||
// totalAdmins: totalAdmins ?? 86,
|
||||
// totalManagers: totalManagers ?? 12,
|
||||
// totalUsers: totalUsers ?? 24,
|
||||
// totalStations: totalStations ?? 8,
|
||||
// };
|
||||
|
||||
// const getStatCards = () => {
|
||||
// switch (userType) {
|
||||
// case "superadmin":
|
||||
// return [
|
||||
// { title: "Total Admins", value: data.totalAdmins },
|
||||
// { title: "Total Managers", value: data.totalManagers },
|
||||
// { title: "Total Users", value: data.totalUsers },
|
||||
// { title: "Total Stations", value: data.totalStations },
|
||||
// ];
|
||||
// case "admin":
|
||||
// return [
|
||||
// { title: "Total Managers", value: data.totalManagers },
|
||||
// { title: "Total Users", value: data.totalUsers },
|
||||
// { title: "Total Stations", value: data.totalStations },
|
||||
// ];
|
||||
// case "manager":
|
||||
// return [
|
||||
// { title: "Total Users", value: data.totalUsers },
|
||||
|
||||
// ];
|
||||
|
||||
// default:
|
||||
// return [];
|
||||
// }
|
||||
// };
|
||||
// return (
|
||||
// <AppTheme>
|
||||
// <Box
|
||||
// sx={{
|
||||
// width: "100%",
|
||||
// maxWidth: "1800px",
|
||||
// mx: "auto",
|
||||
// px: { xs: 2, sm: 1, md: 0 },
|
||||
// background: (theme) => theme.palette.background.default,
|
||||
// }}
|
||||
// >
|
||||
// {/* Dashboard Header */}
|
||||
// <Typography
|
||||
// component="h2"
|
||||
// variant="h4"
|
||||
// sx={{
|
||||
// mb: 3,
|
||||
// }}
|
||||
// >
|
||||
// Dashboard
|
||||
// </Typography>
|
||||
|
||||
// {/* Grid Layout */}
|
||||
// <Grid container spacing={3} columns={12}>
|
||||
// {/* Statistic Cards */}
|
||||
// {getStatCards().map((card, index) => (
|
||||
// <Grid key={index} item xs={12} sm={6} md={3} lg={3}>
|
||||
// <StatCard {...card} />
|
||||
// </Grid>
|
||||
// ))}
|
||||
|
||||
// {/* Charts */}
|
||||
// {userType !== "user" && (
|
||||
// <>
|
||||
// <Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
// <SessionsChart />
|
||||
// </Grid>
|
||||
// <Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
// <ResourcesPieChart />
|
||||
// </Grid>
|
||||
|
||||
// <Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
// <RoundedBarChart />
|
||||
// </Grid>
|
||||
|
||||
// <Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
// <LineChartCard />
|
||||
// </Grid>
|
||||
// </>
|
||||
// )}
|
||||
// </Grid>
|
||||
// </Box>
|
||||
// </AppTheme>
|
||||
// );
|
||||
// }
|
||||
import React, { useEffect } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Box from "@mui/material/Box";
|
||||
|
@ -50,20 +167,18 @@ export default function MainGrid() {
|
|||
maxWidth: "1800px",
|
||||
mx: "auto",
|
||||
px: { xs: 2, sm: 1, md: 0 },
|
||||
background: (theme) => theme.palette.background.default, // #DFECF1 from theme
|
||||
background: (theme) => theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
{/* Dashboard Header */}
|
||||
<Typography
|
||||
component="h2"
|
||||
variant="h4" // Use h4 to match the "Good morning, James!" size and weight
|
||||
variant="h4"
|
||||
sx={{
|
||||
mb: 3,
|
||||
|
||||
|
||||
}}
|
||||
>
|
||||
Dashboard
|
||||
Dashboard
|
||||
</Typography>
|
||||
|
||||
{/* Grid Layout */}
|
||||
|
|
77
src/components/MainGrid/managerGrid.tsx
Normal file
77
src/components/MainGrid/managerGrid.tsx
Normal file
|
@ -0,0 +1,77 @@
|
|||
import React, { useEffect } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import SessionsChart from "../SessionsChart/sessionChart";
|
||||
import ResourcesPieChart from "../ResourcePieChart/resourcePieChart";
|
||||
import RoundedBarChart from "../barChartCard/barChartCard";
|
||||
import LineChartCard from "../LineChartCard/lineChartCard";
|
||||
import { AppDispatch, RootState } from "../../redux/store/store";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
|
||||
import AppTheme from "../../shared-theme/AppTheme";
|
||||
import StatCard from "../StatCard/statCard";
|
||||
|
||||
export default function ManagerGrid() {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const { totalUsers, totalStations } = useSelector(
|
||||
(state: RootState) => state.dashboardReducer
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchDashboardData());
|
||||
}, [dispatch]);
|
||||
|
||||
const statCards = [{ title: "Total Users", value: totalUsers ?? 24 }];
|
||||
|
||||
return (
|
||||
<AppTheme>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
maxWidth: "1800px",
|
||||
mx: "auto",
|
||||
px: { xs: 2, sm: 2, md: 3 },
|
||||
background: (theme) => theme.palette.background.default,
|
||||
}}
|
||||
>
|
||||
{/* Header */}
|
||||
<Typography
|
||||
component="h2"
|
||||
variant="h4"
|
||||
sx={{ mb: 3, fontWeight: 600 }}
|
||||
>
|
||||
Dashboard
|
||||
</Typography>
|
||||
|
||||
{/* Stat Cards - Centered */}
|
||||
<Grid
|
||||
container
|
||||
spacing={3}
|
||||
justifyContent="center"
|
||||
alignItems="stretch"
|
||||
sx={{ mb: 1 }}
|
||||
>
|
||||
{statCards.map((card, index) => (
|
||||
<Grid key={index} item xs={12} sm={8} md={4} lg={3}>
|
||||
<StatCard {...card} />
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
{/* Charts */}
|
||||
<Grid container spacing={3} mt={1}>
|
||||
<Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
<SessionsChart />
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
<ResourcesPieChart />
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={6} lg={6}>
|
||||
<LineChartCard />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</AppTheme>
|
||||
);
|
||||
}
|
248
src/components/MainGrid/userDashboard.tsx
Normal file
248
src/components/MainGrid/userDashboard.tsx
Normal file
|
@ -0,0 +1,248 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Box, Grid, Typography, Divider, Avatar, Chip } from "@mui/material";
|
||||
import {
|
||||
EvStation,
|
||||
AccessTime,
|
||||
DirectionsCar,
|
||||
BookOnline,
|
||||
} from "@mui/icons-material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
|
||||
import { AppDispatch, RootState } from "../../redux/store/store";
|
||||
import { BarChart } from "@mui/x-charts/BarChart";
|
||||
import { LineChart } from "@mui/x-charts/LineChart";
|
||||
import AppTheme from "../../shared-theme/AppTheme";
|
||||
import StatCard from "../StatCard/statCard";
|
||||
|
||||
export default function UserDashboard() {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const { user } = useSelector((state: RootState) => state.profileReducer);
|
||||
const { totalStations } = useSelector(
|
||||
(state: RootState) => state.dashboardReducer
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchDashboardData());
|
||||
}, [dispatch]);
|
||||
|
||||
const statCards = [
|
||||
{
|
||||
title: "Active Bookings",
|
||||
value: 2,
|
||||
icon: <BookOnline color="primary" />,
|
||||
},
|
||||
{
|
||||
title: "Nearby Stations",
|
||||
value: totalStations || 8,
|
||||
icon: <EvStation color="success" />,
|
||||
},
|
||||
{
|
||||
title: "Charges This Month",
|
||||
value: 15,
|
||||
icon: <DirectionsCar color="warning" />,
|
||||
},
|
||||
{
|
||||
title: "Available Slots",
|
||||
value: 4,
|
||||
icon: <AccessTime color="secondary" />,
|
||||
},
|
||||
];
|
||||
|
||||
const upcomingBookings = [
|
||||
{ title: "Indian EV Station - Slot 1", time: "Apr 25, 6:00 PM" },
|
||||
{ title: "Mumbai EV Station - Slot 3", time: "Apr 26, 2:00 PM" },
|
||||
];
|
||||
|
||||
const recentSessions = [
|
||||
{
|
||||
station: "Indian EV Station",
|
||||
time: "Yesterday at 3:00 PM",
|
||||
duration: "1h 30m",
|
||||
},
|
||||
{
|
||||
station: "Delhi EV Station",
|
||||
time: "Apr 22, 5:00 PM",
|
||||
duration: "2h",
|
||||
},
|
||||
];
|
||||
|
||||
const barChartData = [
|
||||
{ category: "Station A", bookings: 5 },
|
||||
{ category: "Station B", bookings: 3 },
|
||||
{ category: "Station C", bookings: 8 },
|
||||
];
|
||||
|
||||
const lineChartData = [
|
||||
{ date: "2025-04-01", charges: 5 },
|
||||
{ date: "2025-04-02", charges: 6 },
|
||||
{ date: "2025-04-03", charges: 4 },
|
||||
{ date: "2025-04-04", charges: 7 },
|
||||
{ date: "2025-04-05", charges: 5 },
|
||||
];
|
||||
|
||||
return (
|
||||
<AppTheme>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
color: "#DE0E1E9",
|
||||
py: 3,
|
||||
}}
|
||||
>
|
||||
{/* Greeting */}
|
||||
<Box display="flex" alignItems="center" px={3} mb={4}>
|
||||
{/* <Avatar
|
||||
sx={{
|
||||
width: 64,
|
||||
height: 64,
|
||||
mr: 2,
|
||||
bgcolor: "",
|
||||
boxShadow: "0 4px 12px rgba(0,0,0,0.2)",
|
||||
border: "2px solid white",
|
||||
fontSize: "2rem",
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{user?.name?.charAt(0).toUpperCase() || "U"}
|
||||
</Avatar> */}
|
||||
<Box>
|
||||
<Typography variant="h3">
|
||||
Welcome back, {user?.name || "User"}!
|
||||
</Typography>
|
||||
<Typography color="#DE0E1E9">
|
||||
Here’s a quick snapshot of your EV activity.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Stat Cards */}
|
||||
<Grid container spacing={3} px={3}>
|
||||
{statCards.map((card, index) => (
|
||||
<Grid item xs={12} sm={6} md={3} key={index}>
|
||||
<StatCard
|
||||
title={card.title}
|
||||
value={card.value}
|
||||
icon={card.icon}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
|
||||
{/* Charts */}
|
||||
<Grid container spacing={3} mt={1} px={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box bgcolor="#D0E1E9" borderRadius={2} p={2}>
|
||||
<Typography variant="h6" color="#000">
|
||||
Bookings by Station
|
||||
</Typography>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
<BarChart
|
||||
dataset={barChartData}
|
||||
xAxis={[
|
||||
{
|
||||
scaleType: "band",
|
||||
dataKey: "category",
|
||||
label: "Station",
|
||||
},
|
||||
]}
|
||||
series={[
|
||||
{
|
||||
dataKey: "bookings",
|
||||
label: "Bookings",
|
||||
color: "#000000",
|
||||
},
|
||||
]}
|
||||
width={500}
|
||||
height={300}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box bgcolor="#D0E1E9" borderRadius={2} p={2}>
|
||||
<Typography variant="h6" color="#000">
|
||||
Daily Charges
|
||||
</Typography>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
<LineChart
|
||||
dataset={lineChartData}
|
||||
xAxis={[
|
||||
{
|
||||
scaleType: "point",
|
||||
dataKey: "date",
|
||||
label: "Date",
|
||||
},
|
||||
]}
|
||||
series={[
|
||||
{
|
||||
dataKey: "charges",
|
||||
label: "Charges",
|
||||
color: "#000000",
|
||||
},
|
||||
]}
|
||||
width={500}
|
||||
height={300}
|
||||
/>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
{/* Bookings & Sessions */}
|
||||
<Grid container spacing={3} mt={1} px={3}>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box bgcolor="#D0E1E9" borderRadius={2} p={2}>
|
||||
<Typography variant="h6" color="#000">
|
||||
Upcoming Bookings
|
||||
</Typography>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
{upcomingBookings.map((booking, idx) => (
|
||||
<Box key={idx} mb={2}>
|
||||
<Typography variant="subtitle1">
|
||||
{booking.title}
|
||||
</Typography>
|
||||
<Chip
|
||||
icon={
|
||||
<AccessTime
|
||||
sx={{
|
||||
color: "#D0E1E9 !important",
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={booking.time}
|
||||
sx={{
|
||||
bgcolor: "#000000",
|
||||
color: "#D0E1E9 !important",
|
||||
"& .MuiChip-label": {
|
||||
color: "#D0E1E9 !important",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
<Grid item xs={12} md={6}>
|
||||
<Box bgcolor="#D0E1E9" borderRadius={2} p={2}>
|
||||
<Typography variant="h6" color="#000">
|
||||
Recent Charging Sessions
|
||||
</Typography>
|
||||
<Divider sx={{ my: 2 }} />
|
||||
{recentSessions.map((session, idx) => (
|
||||
<Box key={idx} mb={2}>
|
||||
<Typography variant="subtitle1">
|
||||
{session.station}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>
|
||||
{session.time} • {session.duration}
|
||||
</Typography>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</AppTheme>
|
||||
);
|
||||
}
|
|
@ -89,17 +89,17 @@ export default function MenuContent({ hidden }: PropType) {
|
|||
userRole === "manager" && {
|
||||
text: "Station Details",
|
||||
icon: <ChecklistSharpIcon />,
|
||||
url: "/panel/manager-station-details", // Placeholder for now
|
||||
url: "/panel/manager-station-details",
|
||||
},
|
||||
userRole === "user" && {
|
||||
text: "Available Slots",
|
||||
icon: <ChecklistSharpIcon />,
|
||||
url: "/panel/all-available-slots", // Placeholder for now
|
||||
url: "/panel/all-available-slots",
|
||||
},
|
||||
userRole === "user" && {
|
||||
text: "Near By Stations",
|
||||
icon: <EvStationIcon />,
|
||||
url: "/panel/external-station-list", // Placeholder for now
|
||||
url: "/panel/external-station-list",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -119,7 +119,7 @@ export default function MenuContent({ hidden }: PropType) {
|
|||
<ListItem
|
||||
key={index}
|
||||
disablePadding
|
||||
sx={{ display: "block",mt:2 }}
|
||||
sx={{ display: "block", mt: 2 }}
|
||||
>
|
||||
<ListItemButton
|
||||
component={Link}
|
||||
|
|
19
src/components/RoleBasedRedirect/roleBasedRedirect.tsx
Normal file
19
src/components/RoleBasedRedirect/roleBasedRedirect.tsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
// src/components/RoleBasedRedirect.tsx
|
||||
import { Navigate } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../redux/reducers";
|
||||
|
||||
const RoleBasedRedirect = () => {
|
||||
const userType = useSelector(
|
||||
(state: RootState) => state.profileReducer.user?.userType
|
||||
);
|
||||
|
||||
if (userType === "user") {
|
||||
return <Navigate to="/panel/booking-list" replace />;
|
||||
}
|
||||
|
||||
// Optional: route others to dashboard or their own start page
|
||||
return <Navigate to="/panel/dashboard" replace />;
|
||||
};
|
||||
|
||||
export default RoleBasedRedirect;
|
|
@ -84,11 +84,12 @@ export default function RoundedBarChart() {
|
|||
const chartSetting = getChartSettings();
|
||||
|
||||
// Data transformation for BarChart
|
||||
const chartData = topStations.map((station) => ({
|
||||
name: station?.ChargingStation?.name,
|
||||
count: parseInt(station.count, 10), // Ensure count is a number
|
||||
const chartData = (topStations ?? []).map((station) => ({
|
||||
name: station?.ChargingStation?.name ?? "Unknown Station",
|
||||
count: parseInt(station?.count ?? "0", 10),
|
||||
}));
|
||||
|
||||
|
||||
return (
|
||||
<Card
|
||||
variant="outlined"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// src/pages/Dashboard
|
||||
|
||||
import * as React from "react";
|
||||
import { Box, CssBaseline, Typography } from "@mui/material";
|
||||
import { useSelector } from "react-redux";
|
||||
import { RootState } from "../../redux/store/store";
|
||||
|
||||
import {
|
||||
chartsCustomizations,
|
||||
|
@ -9,9 +9,12 @@ import {
|
|||
datePickersCustomizations,
|
||||
treeViewCustomizations,
|
||||
} from "./theme/customizations";
|
||||
|
||||
import AppTheme from "../../shared-theme/AppTheme";
|
||||
import MainGrid from "../../components/MainGrid/mainGrid";
|
||||
|
||||
import AdminGrid from "../../components/MainGrid/adminGrid";
|
||||
import ManagerGrid from "../../components/MainGrid/managerGrid";
|
||||
import UserDashboard from "../../components/MainGrid/userDashboard";
|
||||
|
||||
const xThemeComponents = {
|
||||
...chartsCustomizations,
|
||||
|
@ -27,29 +30,52 @@ interface DashboardProps {
|
|||
const Dashboard: React.FC<DashboardProps> = ({
|
||||
disableCustomTheme = false,
|
||||
}) => {
|
||||
|
||||
const userType = useSelector(
|
||||
(state: RootState) => state.profileReducer.user?.userType
|
||||
);
|
||||
|
||||
|
||||
const renderGrid = () => {
|
||||
switch (userType?.toLowerCase()) {
|
||||
case "superadmin":
|
||||
return <MainGrid />;
|
||||
case "admin":
|
||||
return <AdminGrid />;
|
||||
case "manager":
|
||||
return <ManagerGrid />;
|
||||
case "user":
|
||||
return <UserDashboard />;
|
||||
|
||||
default:
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#202020",
|
||||
height: "100vh",
|
||||
textAlign: "center",
|
||||
padding: 2,
|
||||
}}
|
||||
>
|
||||
<Typography color="white">
|
||||
Access Denied: You do not have permission to view
|
||||
this dashboard.
|
||||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<AppTheme
|
||||
{...{ disableCustomTheme }}
|
||||
themeComponents={xThemeComponents}
|
||||
>
|
||||
<CssBaseline enableColorScheme />
|
||||
{!disableCustomTheme ? (
|
||||
<>
|
||||
<MainGrid />
|
||||
</>
|
||||
) : (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
backgroundColor: "#202020",
|
||||
height: "100vh",
|
||||
textAlign: "center",
|
||||
padding: 2,
|
||||
}}
|
||||
></Box>
|
||||
)}
|
||||
{!disableCustomTheme && renderGrid()}
|
||||
</AppTheme>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -18,13 +18,13 @@ interface TopStation {
|
|||
}
|
||||
|
||||
interface DashboardState {
|
||||
totalAdmins: number;
|
||||
totalManagers: number;
|
||||
totalUsers: number;
|
||||
totalStations: number;
|
||||
carPortCounts: CarPortCount[];
|
||||
topStations: TopStation[];
|
||||
totalBookings: number;
|
||||
totalAdmins?: number;
|
||||
totalManagers?: number;
|
||||
totalUsers?: number;
|
||||
totalStations?: number;
|
||||
carPortCounts?: CarPortCount[];
|
||||
topStations?: TopStation[];
|
||||
totalBookings?: number;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ export default function AppRouter() {
|
|||
|
||||
{/* Dashboard Routes */}
|
||||
<Route path="/panel" element={<DashboardLayout />}>
|
||||
|
||||
<Route
|
||||
path="dashboard"
|
||||
element={<ProtectedRoute component={<Dashboard />} />}
|
||||
|
|
Loading…
Reference in a new issue