dev-jaanvi #1

Open
jaanvi wants to merge 155 commits from dev-jaanvi into main
30 changed files with 6554 additions and 969 deletions
Showing only changes of commit df66275d19 - Show all commits

File diff suppressed because it is too large Load diff

27
public/Login.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 MiB

BIN
public/home-img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

BIN
public/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View file

@ -3,6 +3,11 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Gilroy:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../src/index.css">
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#000000" />
<meta <meta

View file

@ -203,13 +203,17 @@ const CustomTable: React.FC<CustomTableProps> = ({
handleClose(); handleClose();
}; };
const filteredRows = rows.filter( const filteredRows = rows.filter((row) => {
(row) => if (!searchQuery.trim()) return true; // Return all rows if searchQuery is empty or whitespace
(row.name && const lowerCaseQuery = searchQuery.toLowerCase().trim();
row.name.toLowerCase().includes(searchQuery.toLowerCase())) || return (
row.registeredAddress.toLowerCase().includes(searchQuery.toLowerCase()) || (row.name && row.name.toLowerCase().includes(lowerCaseQuery)) ||
false (row.registeredAddress &&
row.registeredAddress.toLowerCase().includes(lowerCaseQuery))
); );
});
const indexOfLastRow = currentPage * usersPerPage; const indexOfLastRow = currentPage * usersPerPage;
const indexOfFirstRow = indexOfLastRow - usersPerPage; const indexOfFirstRow = indexOfLastRow - usersPerPage;
@ -237,7 +241,6 @@ const CustomTable: React.FC<CustomTableProps> = ({
color: "#FFFFFF", color: "#FFFFFF",
fontWeight: 500, fontWeight: 500,
fontSize: "18px", fontSize: "18px",
fontFamily: "Gilroy",
}} }}
> >
{/* Dynamic title based on the page type */} {/* Dynamic title based on the page type */}
@ -408,7 +411,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
key={column.id} key={column.id}
sx={{ sx={{
color: "#FFFFFF", color: "#FFFFFF",
fontWeight: "bold", fontWeight: "600",
}} }}
> >
{column.label} {column.label}
@ -429,7 +432,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
<StyledTableCell <StyledTableCell
key={column.id} key={column.id}
sx={{ sx={{
color: "#FFFFFF", color: "#D9D8D8",
backgroundColor: "#272727", backgroundColor: "#272727",
}} }}
> >

View file

@ -209,9 +209,9 @@ const EditSlotModal: React.FC<EditSlotModalProps> = ({
> >
{isAvailable ? "Available" : "Not Available"} {isAvailable ? "Available" : "Not Available"}
</Button> </Button>
<Typography> {/* <Typography>
{isAvailable ? "Available" : "Not Available"} {isAvailable ? "Available" : "Not Available"}
</Typography> </Typography> */}
</Box> </Box>
</Box> </Box>

View file

@ -116,9 +116,15 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
setSelectedVehicles(editRow.allowedCarIds || []); setSelectedVehicles(editRow.allowedCarIds || []);
// Set selectedBrands based on the vehicles associated with the station // Set selectedBrands based on the vehicles associated with the station
const brands = vehicles const brands = editRow?.allowedCarIds
.filter((vehicle) => editRow.allowedCarIds.includes(vehicle.id)) ? vehicles
.map((vehicle) => vehicle.company); .filter((vehicle) =>
editRow.allowedCarIds.includes(vehicle.id)
)
.map((vehicle) => vehicle.company)
: [];
setSelectedBrands(brands); setSelectedBrands(brands);
} else { } else {

View file

@ -28,14 +28,13 @@ export default function Header() {
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
// height: "84px", height: "84px",
// backgroundColor: "#1C1C1C", backgroundColor: "#1C1C1C",
padding: { xs: "20px 12px", sm: "20px 24px" }, padding: { xs: "20px 12px", sm: "20px 24px" },
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
flexDirection: { xs: "column", sm: "row" }, flexDirection: { xs: "column", sm: "row" },
// padding:"0px"
}} }}
> >
<Stack <Stack

View file

@ -6,163 +6,186 @@ import Typography from "@mui/material/Typography";
import { LineChart } from "@mui/x-charts/LineChart"; import { LineChart } from "@mui/x-charts/LineChart";
import { FormControl, MenuItem, Select } from "@mui/material"; import { FormControl, MenuItem, Select } from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import useMediaQuery from "@mui/material/useMediaQuery";
function AreaGradient({ color, id }: { color: string; id: string }) { function AreaGradient({ color, id }: { color: string; id: string }) {
return (
return ( <defs>
<defs> <linearGradient id={id} x1="50%" y1="0%" x2="50%" y2="100%">
<linearGradient id={id} x1="50%" y1="0%" x2="50%" y2="100%"> <stop offset="0%" stopColor={color} stopOpacity={0.5} />
<stop offset="0%" stopColor={color} stopOpacity={0.5} /> <stop offset="100%" stopColor={color} stopOpacity={0} />
<stop offset="100%" stopColor={color} stopOpacity={0} /> </linearGradient>
</linearGradient> </defs>
</defs> );
);
} }
function getDaysInMonth(month: number, year: number) { function getDaysInMonth(month: number, year: number) {
const date = new Date(year, month, 0); const date = new Date(year, month, 0);
const monthName = date.toLocaleDateString("en-US", { const monthName = date.toLocaleDateString("en-US", {
month: "short", month: "short",
}); });
const daysInMonth = date.getDate(); const daysInMonth = date.getDate();
const days = []; const days = [];
let i = 1; let i = 1;
while (days.length < daysInMonth) { while (days.length < daysInMonth) {
days.push(`${monthName} ${i}`); days.push(`${monthName} ${i}`);
i += 1; i += 1;
} }
return days; return days;
} }
export default function LineChartCard() { export default function LineChartCard() {
const theme = useTheme(); const theme = useTheme();
const data = getDaysInMonth(4, 2024); const isXsScreen = useMediaQuery(theme.breakpoints.down("sm"));
const isSmScreen = useMediaQuery(theme.breakpoints.between("sm", "md"));
const data = getDaysInMonth(4, 2024);
const colorPalette = [theme.palette.primary.main];
const [selectedOption, setSelectedOption] = React.useState("Weekly");
const colorPalette = [theme.palette.primary.light]; const handleChange = (event: { target: { value: React.SetStateAction<string> } }) => {
const [selectedOption, setSelectedOption] = React.useState("Weekly"); setSelectedOption(event.target.value);
};
const handleChange = (event: { target: { value: React.SetStateAction<string>; }; }) => {
setSelectedOption(event.target.value);
};
return ( // Calculate responsive dimensions
<Card const getChartHeight = () => {
variant="outlined" if (isXsScreen) return 200;
sx={{ if (isSmScreen) return 220;
width: "553px", return 250;
height: "444px", };
borderRadius: "16px",
"*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#202020",
},
}}
>
<CardContent>
<div
style={{
display: "flex",
alignItems: "center",
color: "#F2F2F2",
}}
>
<Typography
variant="h6"
align="left"
color="#F2F2F2"
sx={{
fontFamily: "Gilroy",
fontWeight: 500,
fontSize: "18px",
lineHeight: "24px",
}}
>
Sales Stats
</Typography>
<FormControl
sx={{
mt: 2,
mb: 2,
backgroundColor: "#202020",
marginLeft: "auto",
marginRight: "16px",
display: "flex",
justifyContent: "center",
alignItems: "center",
// p: 1.5,
color: "#F2F2F2",
width: "149px",
height: "44px",
padding: "12px 16px",
gap: "8px",
}}
>
<Select
value={selectedOption}
onChange={handleChange}
sx={{
//backgroundColor: "#202020",
color: "#D9D8D8",
".MuiSelect-icon": {
color: "#F2F2F2", // Icon color
},
}}
IconComponent={ExpandMoreIcon}
>
<MenuItem value="Monthly">Monthly</MenuItem>
<MenuItem value="Weekly">Weekly</MenuItem>
<MenuItem value="Daily">Daily</MenuItem>
<MenuItem value="Yearly">Yearly</MenuItem>
</Select>
</FormControl>
</div>
<LineChart const getChartMargin = () => {
colors={colorPalette} if (isXsScreen) return { left: 35, right: 10, top: 15, bottom: 15 };
xAxis={[ if (isSmScreen) return { left: 40, right: 15, top: 18, bottom: 18 };
{ return { left: 50, right: 20, top: 20, bottom: 20 };
scaleType: "point", };
data,
tickInterval: (index, i) => (i + 1) % 5 === 0, return (
}, <Card
]} variant="outlined"
series={[ sx={{
{ width: "100%",
id: "direct", height: "auto",
label: "Direct", minHeight: { xs: "360px", sm: "400px", md: "444px" },
showMark: false, borderRadius: "16px",
curve: "linear", border: "none",
stack: "total", "*:where([data-mui-color-scheme='dark']) &": {
area: true, backgroundColor: "#202020",
stackOrder: "ascending", },
data: [ }}
300, 900, 500, 1200, 1500, 1800, 2400, 2100, >
2700, 3000, 1800, 3300, 3600, 3900, 4200, 4500, <CardContent sx={{ padding: { xs: 2, md: 3 }, "&:last-child": { paddingBottom: { xs: 2, md: 3 } } }}>
3900, 4800, 5100, 5400, 4500, 5700, 6000, 6300, <div
6600, 6900, 7200, 7500, 7800, 8100, style={{
], display: "flex",
color: "#FFFFFF", alignItems: "center",
}, flexDirection: isXsScreen ? "column" : "row",
]} color: "#F2F2F2",
height={250} marginBottom: isXsScreen ? 16 : 0,
margin={{ left: 50, right: 20, top: 20, bottom: 20 }} }}
grid={{ horizontal: true }} >
sx={{ <Typography
"& .MuiAreaElement-series-direct": { variant="h6"
fill: "url('#direct')", align={isXsScreen ? "center" : "left"}
}, color="#F2F2F2"
}} sx={{
slotProps={{ fontWeight: 500,
legend: { fontSize: { xs: "16px", sm: "17px", md: "18px" },
hidden: true, lineHeight: "24px",
}, marginBottom: isXsScreen ? 2 : 0,
}} width: isXsScreen ? "100%" : "auto",
> }}
<AreaGradient >
color={theme.palette.primary.light} Sales Stats
id="direct" </Typography>
/> <FormControl
</LineChart> sx={{
</CardContent> mt: isXsScreen ? 0 : 2,
</Card> mb: isXsScreen ? 0 : 2,
); backgroundColor: "#202020",
} marginLeft: isXsScreen ? 0 : "auto",
marginRight: isXsScreen ? 0 : "16px",
display: "flex",
justifyContent: "center",
alignItems: "center",
color: "#F2F2F2",
width: { xs: "100%", sm: "140px", md: "149px" },
height: { xs: "40px", md: "44px" },
padding: { xs: "8px 12px", md: "12px 16px" },
gap: "8px",
}}
>
<Select
value={selectedOption}
onChange={handleChange}
sx={{
fontSize: { xs: "14px", md: "16px" },
color: "#D9D8D8",
".MuiSelect-icon": {
color: "#F2F2F2",
},
}}
IconComponent={ExpandMoreIcon}
>
<MenuItem value="Monthly">Monthly</MenuItem>
<MenuItem value="Weekly">Weekly</MenuItem>
<MenuItem value="Daily">Daily</MenuItem>
<MenuItem value="Yearly">Yearly</MenuItem>
</Select>
</FormControl>
</div>
<LineChart
colors={colorPalette}
xAxis={[
{
scaleType: "point",
data,
tickInterval: (index, i) => isXsScreen
? (i + 1) % 10 === 0
: isSmScreen
? (i + 1) % 7 === 0
: (i + 1) % 5 === 0,
},
]}
series={[
{
id: "direct",
label: "Direct",
showMark: false,
curve: "linear",
stack: "total",
area: true,
stackOrder: "ascending",
data: [
300, 900, 500, 1200, 1500, 1800, 2400, 2100,
2700, 3000, 1800, 3300, 3600, 3900, 4200, 4500,
3900, 4800, 5100, 5400, 4500, 5700, 6000, 6300,
6600, 6900, 7200, 7500, 7800, 8100,
],
color: "#28ACFF",
},
]}
height={getChartHeight()}
margin={getChartMargin()}
grid={{ horizontal: true }}
sx={{
"& .MuiAreaElement-series-direct": {
fill: "url('#direct')",
},
}}
slotProps={{
legend: {
hidden: true,
},
}}
>
<AreaGradient
color={theme.palette.primary.main}
id="direct"
/>
</LineChart>
</CardContent>
</Card>
);
}

View file

@ -1,5 +1,4 @@
import Grid from "@mui/material/Grid";
import Grid from "@mui/material/Grid2";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import SessionsChart from "../SessionsChart/sessionChart"; import SessionsChart from "../SessionsChart/sessionChart";
@ -9,57 +8,43 @@ import RoundedBarChart from "../barChartCard/barChartCard";
import LineChartCard from "../LineChartCard/lineChartCard"; import LineChartCard from "../LineChartCard/lineChartCard";
const data: StatCardProps[] = [ const data: StatCardProps[] = [
{ { title: "Total Charge Stations", value: "86" },
title: "Total Charge Stations", { title: "Charging Completed", value: "12" },
value: "86", { title: "Active Users", value: "24" },
}, { title: "Total Energy Consumed", value: "08" },
{
title: "Charging Completed",
value: "12",
},
{
title: "Active Users",
value: "24",
},
{
title: "Total Energy Consumed",
value: "08",
},
]; ];
export default function MainGrid() { export default function MainGrid() {
return ( return (
<Box sx={{ width: "100%", maxWidth: { sm: "100%", md: "1700px" } }}> <Box sx={{ width: "100%", maxWidth: "1600px", mx: "auto", px: { xs: 2, sm: 1, md: 0 } }}>
{/* cards */} {/* Dashboard Header */}
<Typography component="h2" variant="h6" sx={{ mb: 2 }}> <Typography component="h2" variant="h6" sx={{ mb: 2 }}>
Dashboard Dashboard
</Typography> </Typography>
<Grid
container
spacing={3}
columns={12}
// sx={{ mb: (theme) => theme.spacing(2) }}
>
{data.map((card, index) => (
<Grid key={index} size={{ xs: 12, sm: 6, lg: 3 }}>
<StatCard {...card} />
</Grid>
))}
<Grid size={{ xs: 12, md: 6 }}> {/* Grid Layout */}
<SessionsChart /> <Grid container spacing={3} columns={12}>
</Grid> {/* Statistic Cards */}
<Grid size={{ xs: 12, md: 6 }}> {data.map((card, index) => (
<ResourcesPieChart /> <Grid key={index} item xs={12} sm={6} md={3} lg={3}>
</Grid> <StatCard {...card} />
<Grid size={{ xs: 12, md: 6 }}> </Grid>
<RoundedBarChart /> ))}
</Grid>
<Grid size={{ xs: 12, md: 6 }}> {/* Charts */}
<LineChartCard /> <Grid item xs={12} sm={12} md={6} lg={6}>
</Grid> <SessionsChart />
</Grid> </Grid>
</Box> <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>
);
} }

View file

@ -35,6 +35,16 @@ export default function MenuContent({ hidden }: PropType) {
icon: <ManageAccountsOutlinedIcon />, icon: <ManageAccountsOutlinedIcon />,
url: "/panel/admin-list", url: "/panel/admin-list",
}, },
userRole === "superadmin" && {
text: "Managers",
icon: <PeopleOutlinedIcon />,
url: "/panel/manager-list",
},
userRole === "superadmin" && {
text: "User",
icon: <PeopleOutlinedIcon />,
url: "/panel/user-list",
},
userRole === "superadmin" && { userRole === "superadmin" && {
text: "Roles", text: "Roles",
icon: <AnalyticsOutlinedIcon />, icon: <AnalyticsOutlinedIcon />,

View file

@ -4,111 +4,160 @@ import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent"; import CardContent from "@mui/material/CardContent";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack"; import Stack from "@mui/material/Stack";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
const colorPalette = [ const colorPalette = [
"hsla(202, 69%, 60%, 1)", "hsla(202, 69%, 60%, 1)",
"hsl(204, 48.60%, 72.50%)", "hsl(204, 48.60%, 72.50%)",
"hsl(214, 56.40%, 30.60%)", "hsl(214, 56.40%, 30.60%)",
"hsl(222, 6.80%, 50.80%)", "hsl(222, 6.80%, 50.80%)",
]; ];
const data = [ const data = [
{ title: "Total Resources", value: 50, color: colorPalette[0] }, { title: "Total Resources", value: 50, color: colorPalette[0] },
{ title: "Total Stations", value: 20, color: colorPalette[1] }, { title: "Total Stations", value: 20, color: colorPalette[1] },
{ title: "Station Manager", value: 15, color: colorPalette[2] }, { title: "Station Manager", value: 15, color: colorPalette[2] },
{ title: "Total Booth", value: 15, color: colorPalette[3] }, { title: "Total Booth", value: 15, color: colorPalette[3] },
]; ];
export default function ResourcePieChart() { export default function ResourcePieChart() {
return ( const theme = useTheme();
<Card const isXsScreen = useMediaQuery(theme.breakpoints.down("sm"));
variant="outlined" const isSmScreen = useMediaQuery(theme.breakpoints.between("sm", "md"));
sx={{
display: "flex",
flexDirection: "column",
gap: "12px",
flexGrow: 1,
width: "553px",
height: "324px",
padding: "16px",
borderRadius: "16px",
"*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#202020",
},
}}
>
<CardContent>
<Typography
component="h2"
variant="subtitle2"
color="#F2F2F2"
width="84px"
height="24px"
sx={{
fontWeight: 500,
fontSize: "18px",
lineHeight: "24px",
color: "#FFFFFF",
}}
>
Resources
</Typography>
<Box sx={{ display: "flex", alignItems: "center" }}>
<PieChart
colors={colorPalette}
margin={{
left: 60,
right: 80,
top: 80,
bottom: 80,
}}
series={[
{
data,
innerRadius: 50,
outerRadius: 100,
paddingAngle: 0,
highlightScope: {
faded: "global",
highlighted: "item",
},
},
]}
height={300}
width={300}
slotProps={{
legend: { hidden: true },
}}
></PieChart>
<Stack spacing={1}> const getChartDimensions = () => {
{data.map((entry, index) => ( if (isXsScreen) {
<Stack return {
key={index} height: 240,
direction="row" width: 240,
spacing={1} innerRadius: 40,
alignItems="center" outerRadius: 80,
> margin: { left: 20, right: 20, top: 40, bottom: 40 }
<Box };
sx={{ } else if (isSmScreen) {
width: 16, return {
height: 16, height: 260,
backgroundColor: entry.color, width: 260,
borderRadius: "50%", innerRadius: 50,
}} outerRadius: 90,
/> margin: { left: 40, right: 40, top: 60, bottom: 60 }
<Typography };
variant="body2" } else {
width="100px" return {
height="16px" height: 350,
color="#FFFFFF" width: 350,
> innerRadius: 55,
{entry.title} outerRadius: 110,
</Typography> margin: { left: 60, right: 80, top: 80, bottom: 80 }
</Stack> };
))} }
</Stack> };
</Box>
</CardContent> const dimensions = getChartDimensions();
</Card>
); return (
} <Card
variant="outlined"
sx={{
display: "flex",
flexDirection: "column",
gap: { xs: "8px", sm: "10px", md: "12px" },
flexGrow: 1,
width: "100%",
height: "auto",
minHeight: { xs: "320px", sm: "340px", md: "360px" },
padding: { xs: "12px", sm: "14px", md: "16px" },
borderRadius: "16px",
border: "none",
"*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#202020",
},
}}
>
<CardContent sx={{ padding: 0, "&:last-child": { paddingBottom: 0 } }}>
<Typography
component="h2"
variant="subtitle2"
color="#F2F2F2"
sx={{
fontWeight: 500,
fontSize: { xs: "16px", sm: "17px", md: "18px" },
lineHeight: "24px",
color: "#FFFFFF",
marginBottom: { xs: 1, sm: 1.5, md: 2 },
}}
>
Resources
</Typography>
<Box
sx={{
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: "center",
justifyContent: "center"
}}
>
<PieChart
colors={colorPalette}
margin={dimensions.margin}
series={[
{
data,
innerRadius: dimensions.innerRadius,
outerRadius: dimensions.outerRadius,
paddingAngle: 2,
cornerRadius: 8,
highlightScope: {
faded: "global",
highlighted: "item",
},
},
]}
height={dimensions.height}
width={dimensions.width}
slotProps={{
legend: { hidden: true },
}}
/>
<Stack
spacing={1}
sx={{
mt: { xs: 2, sm: 0 },
ml: { xs: 0, sm: 2 }
}}
>
{data.map((entry, index) => (
<Stack
key={index}
direction="row"
spacing={1}
alignItems="center"
>
<Box
sx={{
width: { xs: 12, sm: 14, md: 16 },
height: { xs: 12, sm: 14, md: 16 },
backgroundColor: entry.color,
borderRadius: "50%",
}}
/>
<Typography
variant="body2"
sx={{
fontSize: { xs: "12px", sm: "13px", md: "14px" },
color: "#FFFFFF",
}}
>
{entry.title}
</Typography>
</Stack>
))}
</Stack>
</Box>
</CardContent>
</Card>
);
}

View file

@ -6,156 +6,146 @@ import Box from "@mui/material/Box";
import Select from "@mui/material/Select"; import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem"; import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl"; import FormControl from "@mui/material/FormControl";
import InputLabel from "@mui/material/InputLabel";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { useTheme } from "@mui/material/styles";
export default function SessionsChart() { export default function SessionsChart() {
const [selectedStation, setSelectedStation] = React.useState( const theme = useTheme();
"Delhi NCR EV Station" const [selectedStation, setSelectedStation] = React.useState(
); "Delhi NCR EV Station"
);
const handleChange = (event: { target: { value: React.SetStateAction<string>; }; }) => { const handleChange = (event: { target: { value: React.SetStateAction<string> } }) => {
setSelectedStation(event.target.value); setSelectedStation(event.target.value);
}; };
return ( return (
<Card <Card
variant="outlined" variant="outlined"
sx={{ sx={{
width: "553px", width: "100%",
height: "324px", height: "auto",
gap: "16px", minHeight: { xs: "260px", sm: "270px", md: "290px" },
borderRadius: "16px", gap: "16px",
padding: "20px", borderRadius: "16px",
"*:where([data-mui-color-scheme='dark']) &": { padding: { xs: "12px", sm: "16px", md: "20px" },
backgroundColor: "#202020", border: "none",
}, "*:where([data-mui-color-scheme='dark']) &": {
}} backgroundColor: "#202020",
> },
<CardContent> }}
<Typography >
variant="h6" <CardContent sx={{ padding: 0, "&:last-child": { paddingBottom: 0 } }}>
align="left" <Typography
color="#F2F2F2" variant="h6"
width="132px" align="left"
height="24px" color="#F2F2F2"
gap={"12px"} sx={{
sx={{ fontWeight: 500,
fontFamily: "Gilroy", fontSize: { xs: "16px", sm: "17px", md: "18px" },
fontWeight: 500, lineHeight: "24px",
fontSize: "18px", letterSpacing: "0%",
lineHeight: "24px", color: "#FAFAFA",
letterSpacing: "0%", marginBottom: { xs: 1, sm: 1.5, md: 2 },
color: "#FAFAFA", }}
}} >
> Charging prices
Charging prices </Typography>
</Typography>
{/* Dropdown button */} {/* Dropdown button */}
<FormControl <FormControl
sx={{ sx={{
mt: 2, mt: { xs: 1, sm: 1.5, md: 2 },
mb: 2, mb: { xs: 1, sm: 1.5, md: 2 },
width: "100%", width: "100%",
// backgroundColor: "#202020", border: "none",
border: "1px solid #454545", borderRadius: "8px",
borderRadius: "8px", }}
}} >
> <Select
value={selectedStation}
<Select onChange={handleChange}
value={selectedStation} label="Select Station"
onChange={handleChange} sx={{
label="Select Station" color: "#D9D8D8",
sx={{ "& .MuiSvgIcon-root": { color: "#F2F2F2" },
//backgroundColor: "#202020", fontSize: { xs: "14px", md: "16px" },
color: "#D9D8D8", }}
"& .MuiSvgIcon-root": { color: "#F2F2F2" }, IconComponent={ExpandMoreIcon}
}} >
IconComponent={ExpandMoreIcon} <MenuItem value="Delhi NCR EV Station">Delhi NCR EV Station</MenuItem>
> <MenuItem value="Mumbai EV Station">Mumbai EV Station</MenuItem>
<MenuItem value="Delhi NCR EV Station"> <MenuItem value="Bangalore EV Station">Bangalore EV Station</MenuItem>
Delhi NCR EV Station <MenuItem value="Pune EV Station">Pune EV Station</MenuItem>
</MenuItem> </Select>
<MenuItem value="Mumbai EV Station"> </FormControl>
Mumbai EV Station
</MenuItem>
<MenuItem value="Bangalore EV Station">
Bangalore EV Station
</MenuItem>
<MenuItem value="Pune EV Station">
Pune EV Station
</MenuItem>
</Select>
</FormControl>
{/* Grid container for the four boxes */} {/* Grid container for the four boxes */}
<Box <Box
sx={{ sx={{
display: "grid", display: "grid",
gridTemplateColumns: { gridTemplateColumns: {
xs: "1fr", xs: "repeat(1, 1fr)", // 1 column on mobile
sm: "repeat(2, 1fr)", sm: "repeat(2, 1fr)", // 2 columns on tablets
}, md: "repeat(2, 1fr)", // 2x2 grid on desktop
gap: { xs: 1, sm: 2 }, },
maxWidth: "750px", gap: { xs: 1, sm: 1.5, md: 2 },
width: "100%", width: "100%",
mx: "auto", }}
}} >
> {[1, 2, 3, 4].map((item) => (
{[1, 2, 3, 4].map((item) => ( <Box
<Box key={item}
key={item} sx={{
sx={{ height: { xs: "105px", sm: "115px", md: "128px" },
height: "84px", borderRadius: "8px",
borderRadius: "8px", p: { xs: "10px", sm: "12px", md: "14px" },
p: "12px 16px", backgroundColor: "#272727",
backgroundColor: "#272727", color: "#D9D8D8",
color: "#D9D8D8", display: "flex",
}} flexDirection: "column",
> justifyContent: "center",
<Typography }}
component="h1" >
variant="body2" <Typography
width="98px" variant="body2"
height="24px" sx={{
fontWeight={400} fontWeight: 400,
fontSize={"14px"} fontSize: { xs: "12px", sm: "13px", md: "14px" },
lineHeight={"24px"} lineHeight: { xs: "20px", md: "24px" },
gutterBottom marginBottom: "4px",
> }}
Basic Charging gutterBottom
</Typography> >
<Box display={"flex"} gap={1}> Basic Charging
<Typography </Typography>
component="h1" <Box display="flex" gap={1} alignItems="center">
variant="subtitle2" <Typography
color="#FFFFFF" variant="subtitle2"
width="40px" color="#FFFFFF"
height={"24px"} sx={{
fontWeight={500} fontWeight: 500,
fontSize="18px" fontSize: { xs: "16px", sm: "17px", md: "18px" },
lineHeight="24px" lineHeight: { xs: "20px", md: "24px" },
gutterBottom }}
> gutterBottom
16.83 >
</Typography> 16.83
</Typography>
<Typography <Typography
width="71px" sx={{
height="24px" fontWeight: 400,
gap="2px" fontSize: { xs: "12px", sm: "13px", md: "14px" },
fontWeight={400} lineHeight: { xs: "20px", md: "24px" },
fontSize={"14px"} }}
lineHeight={"24px"} >
> cents/kWh
cents/kWh </Typography>
</Typography> </Box>
</Box> </Box>
</Box> ))}
))} </Box>
</Box> </CardContent>
</CardContent> </Card>
</Card> );
);
} }

View file

@ -1,59 +1,106 @@
import Card from "@mui/material/Card"; import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent"; import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { useTheme } from "@mui/material/styles";
import useMediaQuery from "@mui/material/useMediaQuery";
export type StatCardProps = { export type StatCardProps = {
title: string; title: string;
value: string; value: string;
}; };
export default function StatCard({ title, value }: StatCardProps) { export default function StatCard({ title, value }: StatCardProps) {
return ( const theme = useTheme();
<Card const isXsScreen = useMediaQuery(theme.breakpoints.only("xs"));
variant="outlined" const isSmScreen = useMediaQuery(theme.breakpoints.only("sm"));
sx={{ const isMdScreen = useMediaQuery(theme.breakpoints.only("md"));
width: "264.5px",
height: "90px", return (
padding: "16px", <Card
borderRadius: "12px", variant="outlined"
gap: "24px", sx={{
"*:where([data-mui-color-scheme='dark']) &": { width: "100%",
backgroundColor: "#202020", height: "100px",
}, padding: {
}} xs: "12px",
> sm: "14px",
<CardContent> md: "10px"
<Typography },
component="h2" borderRadius: "12px",
variant="subtitle2" border: "none",
color="#F2F2F2" gap: "24px",
width={"118px"} "*:where([data-mui-color-scheme='dark']) &": {
height={"14px"} backgroundColor: "#202020",
fontWeight={400} },
fontSize={"12px"} }}
lineHeight={"14px"} >
letterSpacing={"0%"} <CardContent
gutterBottom sx={{
> padding: {
{title} xs: "8px",
</Typography> sm: "12px",
<Typography md: "16px"
component="h1" },
variant="body1" "&:last-child": {
color="#F2F2F2" paddingBottom: {
width={"36px"} xs: "8px",
height={"36px"} sm: "12px",
fontSize={"32px"} md: "16px"
fontWeight={600} }
lineHeight={"36px"} }
letterSpacing={"0%"} }}
gutterBottom >
> <Typography
{value} component="h2"
</Typography> variant="subtitle2"
</CardContent> color="#F2F2F2"
</Card> sx={{
); fontWeight: 400,
} fontSize: {
xs: "10px",
sm: "11px",
md: "12px"
},
lineHeight: {
xs: "12px",
sm: "13px",
md: "14px"
},
letterSpacing: "0%",
width: "auto",
height: "auto",
marginBottom: { xs: "6px", sm: "8px", md: "10px" }, // Added more spacing
}}
gutterBottom
>
{title}
</Typography>
<Typography
component="h1"
variant="body1"
color="#D9D8D8"
sx={{
fontWeight: 600,
fontSize: {
xs: "24px",
sm: "28px",
md: "32px"
},
lineHeight: {
xs: "28px",
sm: "32px",
md: "36px"
},
letterSpacing: "0%",
width: "auto",
height: "auto",
}}
gutterBottom
>
{value}
</Typography>
</CardContent>
</Card>
);
}

View file

@ -13,6 +13,7 @@ import {
import { BarChart } from "@mui/x-charts/BarChart"; import { BarChart } from "@mui/x-charts/BarChart";
import { axisClasses } from "@mui/x-charts/ChartsAxis"; import { axisClasses } from "@mui/x-charts/ChartsAxis";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import useMediaQuery from "@mui/material/useMediaQuery";
// Sample Data // Sample Data
const data = [ const data = [
@ -24,59 +25,100 @@ const data = [
{ name: "Jun", v1: 30 }, { name: "Jun", v1: 30 },
]; ];
// Chart Configuration
const chartSetting = {
yAxis: [
{
label: "Value",
tickFormatter: (value: number) => `${value}`, // Formatting Y-axis ticks
},
],
xAxis: [
{
dataKey: "name",
scaleType: "band" as const,
},
],
width: 500,
height: 300,
sx: {
[`.${axisClasses.left} .${axisClasses.label}`]: {
transform: "translate(-20px, 0)",
},
},
};
export default function RoundedBarChart() { export default function RoundedBarChart() {
const theme = useTheme(); const theme = useTheme();
const isXsScreen = useMediaQuery(theme.breakpoints.down("sm"));
const isSmScreen = useMediaQuery(theme.breakpoints.between("sm", "md"));
const [selectedOption, setSelectedOption] = React.useState("Monthly"); const [selectedOption, setSelectedOption] = React.useState("Monthly");
const handleChange = (event: SelectChangeEvent<string>) => { const handleChange = (event: SelectChangeEvent<string>) => {
setSelectedOption(event.target.value); setSelectedOption(event.target.value);
};
// Responsive chart settings
const getChartSettings = () => {
const baseSettings = {
yAxis: [
{
label: isXsScreen ? "" : "Value",
tickFormatter: (value: number) => `${value}`,
},
],
xAxis: [
{
dataKey: "name",
scaleType: "band" as const,
},
],
sx: {
[`.${axisClasses.left} .${axisClasses.label}`]: {
transform: "translate(-10px, 0)",
},
},
}; };
// Screen-specific settings
if (isXsScreen) {
return {
...baseSettings,
width: 280,
height: 220,
};
} else if (isSmScreen) {
return {
...baseSettings,
width: 380,
height: 260,
};
} else {
return {
...baseSettings,
width: 500,
height: 280,
};
}
};
const chartSetting = getChartSettings();
return ( return (
<Card <Card
variant="outlined" variant="outlined"
sx={{ sx={{
width: "553px", width: "100%",
height: "444px", height: "auto",
minHeight: { xs: "360px", sm: "400px", md: "444px" },
borderRadius: "16px", borderRadius: "16px",
border: "none",
"*:where([data-mui-color-scheme='dark']) &": { "*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#202020", backgroundColor: "#202020",
}, },
}} }}
> >
<CardContent> <CardContent
<Box display="flex" alignItems="center" color="#F2F2F2"> sx={{
padding: { xs: 2, md: 3 },
"&:last-child": { paddingBottom: { xs: 2, md: 3 } },
}}
>
<Box
display="flex"
alignItems="center"
color="#F2F2F2"
flexDirection={isXsScreen ? "column" : "row"}
sx={{ mb: isXsScreen ? 2 : 0 }}
>
<Typography <Typography
variant="h6" variant="h6"
color="#F2F2F2" color="#F2F2F2"
align={isXsScreen ? "center" : "left"}
sx={{ sx={{
fontFamily: "Gilroy",
fontWeight: 500, fontWeight: 500,
fontSize: "18px", fontSize: { xs: "16px", sm: "17px", md: "18px" },
lineHeight: "24px", lineHeight: "24px",
marginBottom: isXsScreen ? 2 : 0,
width: isXsScreen ? "100%" : "auto",
}} }}
> >
Charge Stats Charge Stats
@ -84,13 +126,13 @@ export default function RoundedBarChart() {
<FormControl <FormControl
sx={{ sx={{
mt: 2, mt: isXsScreen ? 0 : 2,
ml: "auto", ml: isXsScreen ? 0 : "auto",
backgroundColor: "#202020", backgroundColor: "#202020",
color: "#F2F2F2", color: "#F2F2F2",
width: "149px", width: { xs: "100%", sm: "140px", md: "149px" },
height: "44px", height: { xs: "40px", md: "44px" },
padding: "12px 16px", padding: { xs: "8px 12px", md: "12px 16px" },
gap: "8px", gap: "8px",
}} }}
> >
@ -98,6 +140,7 @@ export default function RoundedBarChart() {
value={selectedOption} value={selectedOption}
onChange={handleChange} onChange={handleChange}
sx={{ sx={{
fontSize: { xs: "14px", md: "16px" },
color: "#D9D8D8", color: "#D9D8D8",
".MuiSelect-icon": { ".MuiSelect-icon": {
color: "#F2F2F2", color: "#F2F2F2",
@ -113,17 +156,28 @@ export default function RoundedBarChart() {
</FormControl> </FormControl>
</Box> </Box>
<BarChart <Box
dataset={data} sx={{
series={[ display: "flex",
{ justifyContent: "center",
dataKey: "v1", alignItems: "center",
label: "Value", width: "100%",
color: "skyblue", mt: 2,
}, }}
]} >
{...chartSetting} <BarChart
/> borderRadius={0}
dataset={data}
series={[
{
dataKey: "v1",
color: "#52ACDF",
},
]}
layout="vertical"
{...chartSetting}
/>
</Box>
</CardContent> </CardContent>
</Card> </Card>
); );

8
src/global.d.ts vendored Normal file
View file

@ -0,0 +1,8 @@
declare module "*.css";
declare module "@mui/styles/defaultTheme" {
interface DefaultTheme extends Theme {
vars: object;
}
}

View file

@ -1,14 +1,24 @@
body { body {
margin: 0; margin: 0;
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: "Gilroy";
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif; */
font-family: "Gliroy";
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
code { code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace; monospace;
} }
.mui-typography {
font-family: "Gilroy", sans-serif !important;
background-color: rgb(7, 127, 233);
}
.css-1w8ddxu-MuiBarElement-root {
width: 19px !important;
border-radius: 50px !important;
rx: 8;
ry: 8
}

View file

@ -16,7 +16,7 @@ root.render(
position="top-right" position="top-right"
richColors richColors
closeButton closeButton
duration={6000} duration={3000}
/> />
</Provider> </Provider>
</React.StrictMode> </React.StrictMode>

View file

@ -43,9 +43,10 @@ const DashboardLayout: React.FC<LayoutProps> = ({ customStyles }) => {
flexDirection: "column", flexDirection: "column",
height: "100vh", height: "100vh",
flexGrow: 1, flexGrow: 1,
backgroundColor: theme.vars // backgroundColor: theme.vars
? `rgba(${theme.vars.palette.background.defaultChannel} / 1)` // ? `rgba(${theme.vars.palette.background.defaultChannel} / 1)`
: theme.palette.background.default, // : theme.palette.background.default,
backgroundColor: theme.palette.background.default,
overflow: "auto", overflow: "auto",
...customStyles, ...customStyles,
mt: { xs: 8, md: 0 }, mt: { xs: 8, md: 0 },

View file

@ -22,6 +22,7 @@ import { Visibility, VisibilityOff } from "@mui/icons-material";
import { Card, SignInContainer } from "./styled.css.tsx"; import { Card, SignInContainer } from "./styled.css.tsx";
import { CustomIconButton } from "../../../components/AddUserModal/styled.css.tsx"; import { CustomIconButton } from "../../../components/AddUserModal/styled.css.tsx";
import { AppDispatch } from "../../../redux/store/store.ts"; import { AppDispatch } from "../../../redux/store/store.ts";
interface ILoginForm { interface ILoginForm {
email: string; email: string;
password: string; password: string;
@ -34,7 +35,8 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
const { const {
control, control,
handleSubmit, handleSubmit,
formState: { errors, isValid },trigger formState: { errors, isValid },
trigger,
} = useForm<ILoginForm>({ mode: "onChange" }); } = useForm<ILoginForm>({ mode: "onChange" });
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
const router = useNavigate(); const router = useNavigate();
@ -48,15 +50,15 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
}; };
const togglePasswordVisibility = (e: React.MouseEvent) => { const togglePasswordVisibility = (e: React.MouseEvent) => {
e.preventDefault(); // Prevent focus loss e.preventDefault();
setShowPassword((prev) => !prev); setShowPassword((prev) => !prev);
}; };
const onSubmit: SubmitHandler<ILoginForm> = async (data: ILoginForm) => { const onSubmit: SubmitHandler<ILoginForm> = async (data: ILoginForm) => {
const isValid = await trigger(); // This triggers validation for all fields const isValid = await trigger();
if (!isValid) { if (!isValid) {
return; // Stop submission if there are errors return;
} }
try { try {
const response = await dispatch(loginUser(data)).unwrap(); const response = await dispatch(loginUser(data)).unwrap();
if (response?.data?.token) { if (response?.data?.token) {
@ -70,66 +72,90 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
return ( return (
<AppTheme {...props}> <AppTheme {...props}>
<SignInContainer direction="column" justifyContent="space-between"> <SignInContainer direction="column" justifyContent="space-between">
<Grid container sx={{ height: "100vh" }}> <Grid container sx={{ minHeight: "100vh" }}>
{/* Image Section */}
<Grid <Grid
item item
xs={0} xs={0}
sm={0} sm={0}
md={7} md={7}
sx={{ sx={{
background: `url('/mainPageLogo.png') center/cover no-repeat`, background: `url('/Login.svg') center/cover no-repeat`,
// height: { xs: "0%", sm: "50%", md: "100%" },
backgroundSize: "cover", backgroundSize: "cover",
display: { xs: "none", md: "block" }, // Hide the image on xs and sm screens display: { xs: "none", md: "block" },
}} position: "relative",
/>
{/* Form Section */}
<Grid
item
xs={12}
md={5}
width="408px"
height="498px"
sx={{
backgroundColor: "black",
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
padding: { xs: "2rem", md: "3rem", lg: "3rem" },
height: "auto",
}} }}
> >
<Box <Box
sx={{ sx={{
textAlign: "center", position: "absolute",
marginBottom: "1rem", top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
display: { xs: "none", md: "block" },
}} }}
> >
<img <img
src="/evLogo.png" src="/evLogo.png"
alt="Logo" alt="Logo"
style={{ style={{
justifyContent: "center", width: "250px",
width: "180px",
height: "auto", height: "auto",
}} }}
/> />
</Box> </Box>
</Grid>
{/* Form Section */}
<Grid
item
xs={12}
md={5}
sx={{
backgroundColor: "black",
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
padding: { xs: "1.5rem", sm: "2rem", md: "3rem" },
position: "relative",
}}
>
<Box
sx={{
display: { xs: "flex", md: "none" },
justifyContent: "center",
alignItems: "center",
width: "100%",
mb: 4,
}}
>
<img
src="/evLogo.png"
alt="Logo"
style={{
width: "200px",
maxWidth: "100%",
height: "auto",
}}
/>
</Box>
<Typography <Typography
variant="h3" variant="h3"
width={"408px"}
height={"46px"}
sx={{ sx={{
color: "white", color: "white",
textAlign: "center", textAlign: "center",
fontSize: { fontSize: {
xs: "2rem", xs: "1.8rem",
sm: "2.2rem", sm: "2.2rem",
md: "36px", md: "2.5rem",
}, },
width: "100%",
mb: { xs: 2, md: 3 },
mt: { xs: 0, md: 0 },
}} }}
> >
Welcome Back! Welcome Back!
@ -138,11 +164,12 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<Card <Card
variant="outlined" variant="outlined"
sx={{ sx={{
width: { xs: "100%", sm: "300px", lg: "408px" }, width: { xs: "100%", sm: "90%", md: "90%", lg: "408px" },
height:{lg:"428px"}, maxWidth: "408px",
padding: "24px", minHeight: { xs: "auto", md: "428px" },
padding: { xs: "16px", sm: "20px", md: "24px" },
borderRadius: "9px", borderRadius: "9px",
border: "1px solidrgb(45, 48, 49)", border: "none",
"*:where([data-mui-color-scheme='dark']) &": { "*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#1E1E1E", backgroundColor: "#1E1E1E",
}, },
@ -155,7 +182,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
gap: 2, gap: { xs: 1.5, md: 2 },
}} }}
> >
<Typography <Typography
@ -164,8 +191,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
sx={{ sx={{
textAlign: "center", textAlign: "center",
color: "white", color: "white",
fontFamily: "Gilroy", fontSize: { xs: "20px", md: "24px" },
fontSize: "24px",
}} }}
> >
Login Login
@ -176,24 +202,24 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
sx={{ sx={{
textAlign: "center", textAlign: "center",
color: "white", color: "white",
fontFamily: "Gilroy", fontSize: { xs: "14px", md: "16px" },
fontSize: "16px", mb: 1,
}} }}
> >
Log in with your email and password Log in with your email and password
</Typography> </Typography>
{/* -------------------------------- Email Field ----------------- */} {/* Email Field */}
<FormControl sx={{ width: "100%" }}> <FormControl sx={{ width: "100%" }}>
<FormLabel <FormLabel
htmlFor="email" htmlFor="email"
sx={{ sx={{
fontSize: { fontSize: {
xs: "0.9rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
}, },
color: "white", color: "white",
fontFamily: "Gilroy, sans-serif", mb: 0.5,
}} }}
> >
Email Email
@ -232,12 +258,10 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
} }
InputProps={{ InputProps={{
sx: { sx: {
height: "50px", height: { xs: "45px", md: "50px" },
alignItems: "center", alignItems: "center",
backgroundColor: backgroundColor:
"#1E1F1F", "#1E1F1F",
fontFamily:
"Gilroy, sans-serif",
}, },
}} }}
sx={{ sx={{
@ -265,7 +289,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
"& input": { "& input": {
color: "white", color: "white",
fontSize: { fontSize: {
xs: "0.9rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
}, },
fontFamily: fontFamily:
@ -284,17 +308,18 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
/> />
</FormControl> </FormControl>
{/* -------------------------------- Password Field ----------------- */} {/* Password Field */}
<FormControl sx={{ width: "100%" }}> <FormControl sx={{ width: "100%" }}>
<FormLabel <FormLabel
htmlFor="password" htmlFor="password"
sx={{ sx={{
fontSize: { fontSize: {
xs: "0.9rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
}, },
color: "white", color: "white",
fontFamily: "Gilroy, sans-serif", fontFamily: "Gilroy, sans-serif",
mb: 0.5,
}} }}
> >
Password Password
@ -341,6 +366,9 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
: "primary" : "primary"
} }
InputProps={{ InputProps={{
sx: {
height: { xs: "45px", md: "50px" },
},
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
<CustomIconButton <CustomIconButton
@ -383,18 +411,14 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
"& input": { "& input": {
color: "white", color: "white",
fontSize: { fontSize: {
xs: "0.9rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
}, },
fontFamily:
"Gilroy, sans-serif",
}, },
"& .MuiInputBase-input::placeholder": "& .MuiInputBase-input::placeholder":
{ {
color: "white", color: "white",
opacity: 1, opacity: 1,
fontFamily:
"Gilroy, sans-serif",
}, },
}} }}
/> />
@ -402,13 +426,16 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
/> />
</FormControl> </FormControl>
{/* Remember me and Forgot Password */}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
justifyContent: "space-between", justifyContent: "space-between",
color: "white", color: "white",
alignItems: "center", alignItems: "center",
flexWrap: "wrap", flexWrap: { xs: "wrap", sm: "nowrap" },
gap: 1,
mt: 1,
}} }}
> >
<FormControlLabel <FormControlLabel
@ -416,10 +443,8 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<Checkbox <Checkbox
value="remember" value="remember"
sx={{ sx={{
width: 20, width: { xs: 16, md: 20 },
height: 20, height: { xs: 16, md: 20 },
fontFamily:
"Gilroy, sans-serif",
border: "2px solid #4b5255", border: "2px solid #4b5255",
borderRadius: "4px", borderRadius: "4px",
backgroundColor: backgroundColor:
@ -440,7 +465,19 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
}} }}
/> />
} }
label="Remember me" label={
<Typography
sx={{
fontSize: {
xs: "0.75rem",
sm: "0.875rem",
md: "1rem"
}
}}
>
Remember me
</Typography>
}
/> />
<Link <Link
@ -450,9 +487,13 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
variant="body2" variant="body2"
sx={{ sx={{
alignSelf: "center", alignSelf: "center",
fontFamily: "Gilroy, sans-serif",
color: "#01579b", color: "#01579b",
textDecoration: "none", textDecoration: "none",
fontSize: {
xs: "0.75rem",
sm: "0.875rem",
md: "1rem"
},
}} }}
> >
Forgot password? Forgot password?
@ -462,18 +503,22 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
open={open} open={open}
handleClose={handleClose} handleClose={handleClose}
/> />
{/* Login Button */}
<Button <Button
type="submit" type="submit"
fullWidth fullWidth
disabled={!isValid} disabled={!isValid}
sx={{ sx={{
color: "white", color: "#ffffff !important",
fontFamily: "Gilroy, sans-serif", fontWeight: 500,
backgroundColor: "#52ACDF", backgroundColor: "#52ACDF",
"&:hover": { "&:hover": {
backgroundColor: "#52ACDF", backgroundColor: "#52ACDF",
opacity: 0.9,
}, },
padding: { xs: "8px 0", md: "10px 0" },
mt: { xs: 2, md: 3 },
fontSize: { xs: "0.875rem", md: "1rem" },
}} }}
> >
Login Login
@ -485,4 +530,4 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
</SignInContainer> </SignInContainer>
</AppTheme> </AppTheme>
); );
} }

View file

@ -245,7 +245,7 @@ export default function SignUp(props: { disableCustomTheme?: boolean }) {
<FormLabel htmlFor="phone">Phone Number</FormLabel> <FormLabel htmlFor="phone">Phone Number</FormLabel>
<MuiPhoneNumber <MuiPhoneNumber
defaultCountry="in" defaultCountry="in"
onChange={handlePhoneChange} onChange={(value) => handlePhoneChange(value as string)}
value={control._formValues.phone} value={control._formValues.phone}
required required
error={!!errors.phone} error={!!errors.phone}

View file

@ -0,0 +1,228 @@
import React from "react";
import { Box, Button, Container, Grid, Typography } from "@mui/material";
import { useNavigate } from "react-router-dom"; // Import useNavigate for navigation
import SearchIcon from "@mui/icons-material/Search";
const LandingPage = () => {
const navigate = useNavigate(); // Initialize useNavigate
const handleLoginClick = () => {
navigate("/login"); // Redirect to the login page
};
return (
<Box
sx={{
background: `radial-gradient(circle at top left, rgba(125,121,87,0.992) 10%, rgba(67,92,106,0.8) 40%, rgba(55,47,65,1) 70%),
radial-gradient(circle at center, rgba(109, 102, 102, 0.7) 0%, rgba(67,92,106,0.6) 50%, rgba(55,47,65,0.9) 70%),
radial-gradient(circle at top right, rgba(61,42,87,1) 30%, rgba(55,47,65,1) 60%, rgba(40,40,40,0.8) 70%)`,
color: "white",
minHeight: "100vh",
fontFamily: "Inter",
}}
>
{/* Navbar */}
<Box
component="nav"
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
py: 2,
px: 3,
maxWidth: "1200px",
mx: "auto",
fontFamily: "Inter",
}}
>
<img
src="/evLogo.png"
alt="DigiEv Logo"
style={{ height: "40px" }}
/>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: 2,
}}
>
<SearchIcon
sx={{
fontSize: "24px",
cursor: "pointer",
color: "#364056",
}}
/>
<Button
type="button" // Changed to "button" to avoid form submission
onClick={handleLoginClick} // Trigger navigation on click
sx={{
backgroundColor: "#52ACDF",
color: "white",
borderRadius: "8px",
width: "117px",
fontFamily: "Inter",
textTransform: "none",
"&:hover": { backgroundColor: "#439BC1" },
}}
>
Login
</Button>
</Box>
</Box>
{/* Hero Section */}
<Container
sx={{
py: 8,
justifyContent: "space-between",
fontFamily: "Inter",
}}
>
<Grid
container
spacing={4}
alignItems="center"
justifyContent="center"
>
{/* Text Section */}
<Grid
item
xs={12}
md={6}
sx={{
height: { xs: "auto", md: "400px" },
display: "flex",
flexDirection: "column",
justifyContent: "center",
}}
>
<Typography
sx={{
fontFamily: "Inter",
fontWeight: 600,
fontSize: "40px",
lineHeight: "120%",
letterSpacing: "0px",
marginBottom: "16px",
}}
>
Empower Your Business With{" "}
<Box component="span" sx={{ color: "#52ACDF" }}>
Digital Evolution
</Box>
.
</Typography>
<Typography
variant="body1"
sx={{
fontFamily: "Inter",
color: "#CACACA",
marginBottom: "24px",
fontWeight: 400,
fontSize: "20px",
lineHeight: "120%",
}}
>
DigiEv is your one-stop destination for transforming
challenges into opportunities through innovative
technology, seamless integration, and expert
solutions.
</Typography>
<Button
type="submit"
sx={{
backgroundColor: "#52ACDF",
color: "white",
borderRadius: "8px",
width: "117px",
textTransform: "none",
fontFamily: "Inter",
"&:hover": { backgroundColor: "#439BC1" },
}}
>
Get in Touch
</Button>
</Grid>
{/* Image Section */}
<Grid
item
xs={12}
md={6}
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
<img
src="/home.png"
alt="Dashboard"
style={{
maxHeight: "100%",
maxWidth: "100%",
objectFit: "contain",
borderRadius: "8px",
}}
/>
</Grid>
</Grid>
</Container>
<Container maxWidth="lg">
{" "}
<Grid container spacing={4} textAlign="center">
{" "}
<Grid item xs={12} md={4}>
{" "}
<Typography
variant="h3"
fontWeight="bold"
color="#1e88e5"
>
{" "}
50+{" "}
</Typography>{" "}
<Typography variant="body2" color="gray">
{" "}
Successful Digital Transformations{" "}
</Typography>{" "}
</Grid>{" "}
<Grid item xs={12} md={4}>
{" "}
<Typography
variant="h3"
fontWeight="bold"
color="#1e88e5"
>
{" "}
100%{" "}
</Typography>{" "}
<Typography variant="body2" color="gray">
{" "}
Client Satisfaction{" "}
</Typography>{" "}
</Grid>{" "}
<Grid item xs={12} md={4}>
{" "}
<Typography
variant="h3"
fontWeight="bold"
color="#1e88e5"
>
{" "}
20+{" "}
</Typography>{" "}
<Typography variant="body2" color="gray">
{" "}
Global Partnerships{" "}
</Typography>{" "}
</Grid>{" "}
</Grid>{" "}
</Container>
</Box>
);
};
export default LandingPage;

View file

@ -118,8 +118,8 @@ export default function StationList() {
return { return {
id: station.id, id: station.id,
srno: index + 1, srno: index + 1,
name: station.name, name: station.name || "N/A",
registeredAddress: station.registeredAddress, registeredAddress: station.registeredAddress || "N/A",
totalSlots: station.totalSlots, totalSlots: station.totalSlots,
vehicles: vehicleDisplay, // Add the formatted vehicle display here vehicles: vehicleDisplay, // Add the formatted vehicle display here
status: status:

View file

@ -17,7 +17,6 @@ export default function UserList() {
const [viewModal, setViewModal] = useState<boolean>(false); const [viewModal, setViewModal] = useState<boolean>(false);
const { reset } = useForm(); const { reset } = useForm();
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
const users = useSelector((state: RootState) => state.userReducer.users); const users = useSelector((state: RootState) => state.userReducer.users);
@ -65,7 +64,6 @@ export default function UserList() {
name, name,
email, email,
phone, phone,
}) })
); );
await dispatch(userList()); await dispatch(userList());
@ -76,24 +74,21 @@ export default function UserList() {
const categoryColumns: Column[] = [ const categoryColumns: Column[] = [
{ id: "srno", label: "Sr No" }, { id: "srno", label: "Sr No" },
{ id: "name", label: "Name" }, { id: "name", label: "User Name" },
{ id: "email", label: "Email" }, { id: "email", label: "Email" },
{ id: "phone", label: "Phone" }, { id: "phone", label: "Phone" },
{ id: "action", label: "Action", align: "center" }, { id: "action", label: "Action", align: "center" },
]; ];
const categoryRows = users?.length const categoryRows = users?.length
? users.map((user, index) => ({ ? users.map((user, index) => ({
id: user.id, id: user.id,
srno: index + 1, srno: index + 1,
name: user.name, name: user.name,
email: user.email, email: user.email,
phone: user.phone || "NA", // Ensures it's a string phone: user.phone || "NA", // Ensures it's a string
})) }))
: []; : [];
return ( return (
<> <>

View file

@ -79,6 +79,7 @@ export const createAdmin = createAsyncThunk<
>("/create-admin", async (data, { rejectWithValue }) => { >("/create-admin", async (data, { rejectWithValue }) => {
try { try {
const response = await http.post("/create-admin", data); const response = await http.post("/create-admin", data);
toast.success("Admin created successfully");
return response.data; return response.data;
} catch (error: any) { } catch (error: any) {
return rejectWithValue( return rejectWithValue(

View file

@ -63,7 +63,7 @@ export const addManager = createAsyncThunk<
toast.success("Manager created successfully"); toast.success("Manager created successfully");
return response.data?.data; return response.data?.data;
} catch (error: any) { } catch (error: any) {
toast.error("Error creating manager: " + error.message); toast.error("Error creating manager: " + error.response?.data?.message);
return rejectWithValue( return rejectWithValue(
error.response?.data?.message || "An error occurred" error.response?.data?.message || "An error occurred"
); );

View file

@ -9,6 +9,7 @@ import DashboardLayout from "./layouts/DashboardLayout";
// Page imports // Page imports
const Login = lazy(() => import("./pages/Auth/Login")); const Login = lazy(() => import("./pages/Auth/Login"));
const SignUp = lazy(() => import("./pages/Auth/SignUp")); const SignUp = lazy(() => import("./pages/Auth/SignUp"));
const LandingPage = lazy(() => import("./pages/LandingPage"));
const Dashboard = lazy(() => import("./pages/Dashboard")); const Dashboard = lazy(() => import("./pages/Dashboard"));
const VehicleList = lazy(() => import("./pages/VehicleList")); const VehicleList = lazy(() => import("./pages/VehicleList"));
const AdminList = lazy(() => import("./pages/AdminList")); const AdminList = lazy(() => import("./pages/AdminList"));
@ -43,7 +44,7 @@ export default function AppRouter() {
<Suspense fallback={<LoadingComponent />}> <Suspense fallback={<LoadingComponent />}>
<BaseRoutes> <BaseRoutes>
{/* Default Route */} {/* Default Route */}
<Route element={<Navigate to="/login" replace />} index /> <Route path="" element={<LandingPage /> } />
{/* Auth Routes */} {/* Auth Routes */}
<Route path=""> <Route path="">
@ -110,7 +111,11 @@ export default function AppRouter() {
/> />
<Route <Route
path="external-station-list" path="external-station-list"
element={<ProtectedRoute component={<ExternalStationList />} />} element={
<ProtectedRoute
component={<ExternalStationList />}
/>
}
/> />
</Route> </Route>

View file

@ -6,19 +6,12 @@ import { dataDisplayCustomizations } from "./customizations/dataDisplay";
import { feedbackCustomizations } from "./customizations/feedback"; import { feedbackCustomizations } from "./customizations/feedback";
import { navigationCustomizations } from "./customizations/navigation"; import { navigationCustomizations } from "./customizations/navigation";
import { surfacesCustomizations } from "./customizations/surfaces"; import { surfacesCustomizations } from "./customizations/surfaces";
import { colorSchemes, typography, shadows, shape } from "./themePrimitives"; import { colorSchemes, shadows, shape } from "./themePrimitives";
declare module "@mui/styles/defaultTheme" {
interface DefaultTheme extends Theme {
vars: object;
}
}
interface AppThemeProps { interface AppThemeProps {
children: React.ReactNode; children: React.ReactNode;
/**
* This is for the docs site. You can ignore it or remove it.
*/
disableCustomTheme?: boolean; disableCustomTheme?: boolean;
themeComponents?: ThemeOptions["components"]; themeComponents?: ThemeOptions["components"];
} }
@ -30,21 +23,23 @@ export default function AppTheme(props: AppThemeProps) {
? {} ? {}
: createTheme({ : createTheme({
palette: { palette: {
mode: "dark", // Enforcing dark mode across the app mode: "dark",
background: { background: {
default: "#111111", // Dark background color default: "#111111",
paper: "#1e1e1e", // Darker background for cards, containers, etc. paper: "#1e1e1e",
}, },
text: { text: {
primary: "#ffffff", // White text for readability primary: "#ffffff",
secondary: "#b0b0b0", // Lighter secondary text secondary: "#b0b0b0",
}, },
}, },
typography: {
fontFamily: "Gilroy, sans-serif",
},
cssVariables: { cssVariables: {
colorSchemeSelector: "data-mui-color-scheme", colorSchemeSelector: "data-mui-color-scheme",
cssVarPrefix: "template", cssVarPrefix: "template",
}, },
typography,
shadows, shadows,
shape, shape,
components: { components: {

View file

@ -11,10 +11,22 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"jsx": "react-jsx", "jsx": "react-jsx",
"types": ["react", "react-dom"], "types": [
"lib": ["dom", "dom.iterable", "esnext"], "react",
"react-dom"
],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"moduleResolution": "node",
"esModuleInterop": true,
"resolveJsonModule": true,
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": [
"./src/*"
]
} }
} }
} }