dev-jaanvi #1

Open
jaanvi wants to merge 155 commits from dev-jaanvi into main
34 changed files with 7477 additions and 3311 deletions
Showing only changes of commit 6e445da965 - Show all commits

File diff suppressed because it is too large Load diff

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

0
public/mobileLogo.png Normal file
View file

View file

@ -373,4 +373,4 @@ export default function AddBookingModal({
</Box> </Box>
</Modal> </Modal>
); );
} }

View file

@ -5,6 +5,7 @@ import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff"; import VisibilityOff from "@mui/icons-material/VisibilityOff";
import { useForm, Controller } from "react-hook-form"; import { useForm, Controller } from "react-hook-form";
import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css";
import { autofillFix } from "../../shared-theme/customizations/autoFill";
//By Jaanvi : Edit Model :: 11-feb-25 //By Jaanvi : Edit Model :: 11-feb-25
interface AddEditCategoryModalProps { interface AddEditCategoryModalProps {
@ -157,6 +158,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "50%", width: "50%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -188,8 +190,11 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
{...field} {...field}
required required
placeholder="Enter Admin Name" placeholder="Enter Admin Name"
// autoComplete="new-username"
type="text"
fullWidth fullWidth
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
/> />
@ -202,6 +207,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "50%", width: "50%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -226,6 +232,8 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
id="email" id="email"
type="email" type="email"
placeholder="Email" placeholder="Email"
autoComplete="new-email"
sx={{ marginTop: 1 }}
required required
fullWidth fullWidth
color={ color={
@ -247,6 +255,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "50%", width: "50%",
...autofillFix,
}} }}
> >
<Typography <Typography
@ -276,6 +285,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
{...field} {...field}
required required
placeholder="Enter Password" placeholder="Enter Password"
autoComplete="new-password"
type={ type={
showPassword showPassword
? "text" ? "text"
@ -289,6 +299,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
: "primary" : "primary"
} }
size="small" size="small"
sx={{ marginTop: 1 }}
slotProps={{ slotProps={{
input: { input: {
endAdornment: ( endAdornment: (
@ -324,6 +335,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "50%", width: "50%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -353,6 +365,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
required required
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={errors.phone?.message} helperText={errors.phone?.message}
/> />
@ -367,6 +380,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "50%", width: "50%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -387,6 +401,7 @@ const AddEditCategoryModal: React.FC<AddEditCategoryModalProps> = ({
<CustomTextField <CustomTextField
{...field} {...field}
required required
sx={{ marginTop: 1 }}
placeholder="Enter Address" placeholder="Enter Address"
fullWidth fullWidth
size="small" size="small"

View file

@ -19,6 +19,7 @@ import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { RootState } from "../../redux/reducers.ts"; import { RootState } from "../../redux/reducers.ts";
import { stationList } from "../../redux/slices/stationSlice.ts"; import { stationList } from "../../redux/slices/stationSlice.ts";
import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
export default function AddManagerModal({ export default function AddManagerModal({
open, open,
@ -120,7 +121,7 @@ export default function AddManagerModal({
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
{/* Manager Name */} {/* Manager Name */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
Manager Name Manager Name
</Typography> </Typography>
@ -128,6 +129,8 @@ export default function AddManagerModal({
fullWidth fullWidth
placeholder="Enter Manager Name" placeholder="Enter Manager Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={ helperText={
errors.name ? errors.name.message : "" errors.name ? errors.name.message : ""
@ -157,17 +160,43 @@ export default function AddManagerModal({
{/* Station Dropdown */} {/* Station Dropdown */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1 }}>
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
>
Select Station Select Station
</Typography> </Typography>
<FormControl fullWidth error={!!errors.stationName}> <FormControl
<InputLabel>Select Station</InputLabel> fullWidth
size="small"
error={!!errors.stationName}
>
<Select <Select
{...register("stationName", { {...register("stationName", {
required: "Station Name is required", required: "Station Name is required",
})} })}
sx={{ marginTop: 1 }}
displayEmpty
defaultValue="" defaultValue=""
size="small" renderValue={(selected) => {
if (!selected) {
return (
<Typography color="text.secondary">
Choose Station
</Typography>
);
}
return selected;
}}
MenuProps={{
PaperProps: {
style: {
maxHeight: 224,
},
},
}}
> >
{Array.isArray(stations) && {Array.isArray(stations) &&
stations.length > 0 ? ( stations.length > 0 ? (
@ -186,7 +215,11 @@ export default function AddManagerModal({
)} )}
</Select> </Select>
{errors.stationName && ( {errors.stationName && (
<Typography color="error" variant="body2"> <Typography
color="error"
variant="body2"
sx={{ mt: 0.5 }}
>
{errors.stationName.message} {errors.stationName.message}
</Typography> </Typography>
)} )}
@ -197,7 +230,7 @@ export default function AddManagerModal({
{/* Email and Password */} {/* Email and Password */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
{/* Email */} {/* Email */}
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
Email Email
</Typography> </Typography>
@ -205,6 +238,9 @@ export default function AddManagerModal({
fullWidth fullWidth
placeholder="Enter Manager Email" placeholder="Enter Manager Email"
size="small" size="small"
sx={{ marginTop: 1 }}
autoComplete="new-email"
error={!!errors.email} error={!!errors.email}
helperText={ helperText={
errors.email ? errors.email.message : "" errors.email ? errors.email.message : ""
@ -220,7 +256,7 @@ export default function AddManagerModal({
</Box> </Box>
{/* Password */} {/* Password */}
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
Password Password
</Typography> </Typography>
@ -244,6 +280,9 @@ export default function AddManagerModal({
<CustomTextField <CustomTextField
{...field} {...field}
required required
sx={{ marginTop: 1 }}
autoComplete="new-password"
placeholder="Enter Password" placeholder="Enter Password"
type={ type={
showPassword ? "text" : "password" showPassword ? "text" : "password"
@ -286,7 +325,7 @@ export default function AddManagerModal({
{/* Phone Number */} {/* Phone Number */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
Phone Number Phone Number
</Typography> </Typography>
@ -294,6 +333,8 @@ export default function AddManagerModal({
fullWidth fullWidth
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={ helperText={
errors.phone ? errors.phone.message : "" errors.phone ? errors.phone.message : ""

View file

@ -38,13 +38,17 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => {
<DialogTitle>Add EV Slot</DialogTitle> <DialogTitle>Add EV Slot</DialogTitle>
<DialogContent> <DialogContent>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<Typography variant="body2" fontWeight={500}>
Date
</Typography>
<TextField <TextField
{...register("date", { {...register("date", {
required: "Date is required", required: "Date is required",
validate: (value) => validate: (value) =>
value >= today || "Date cannot be in the past", value >= today || "Date cannot be in the past",
})} })}
label="Date" // label="Date"
// sx={{ marginTop: 1 }}
type="date" type="date"
fullWidth fullWidth
margin="normal" margin="normal"
@ -58,12 +62,16 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => {
// Set the min value to today's date // Set the min value to today's date
inputProps={{ min: today }} inputProps={{ min: today }}
/> />
<Typography variant="body2" fontWeight={500}>
Start Hour
</Typography>
<TextField <TextField
{...register("startHour", { {...register("startHour", {
required: "Start hour is required", required: "Start hour is required",
})} })}
label="Start Hour" // label="Start Hour"
type="time" type="time"
// sx={{ marginTop: 1 }}
fullWidth fullWidth
margin="normal" margin="normal"
slotProps={{ slotProps={{
@ -74,12 +82,16 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => {
error={!!errors.startHour} error={!!errors.startHour}
helperText={errors.startHour?.message} helperText={errors.startHour?.message}
/> />
<Typography variant="body2" fontWeight={500}>
End Hour
</Typography>
<TextField <TextField
{...register("endHour", { {...register("endHour", {
required: "End hour is required", required: "End hour is required",
})} })}
label="End Hour" // label="End Hour"
type="time" type="time"
// sx={{ marginTop: 1 }}
fullWidth fullWidth
margin="normal" margin="normal"
InputLabelProps={{ InputLabelProps={{
@ -95,10 +107,13 @@ const AddSlotModal = ({ open, handleClose, handleAddSlot }: any) => {
justifyContent="space-between" justifyContent="space-between"
gap={2} gap={2}
> >
<Button <Button
onClick={() => setIsAvailable((prev) => !prev)} onClick={() => setIsAvailable((prev) => !prev)}
variant={isAvailable ? "contained" : "outlined"} variant={isAvailable ? "contained" : "outlined"}
color="primary" color="primary"
sx={{ marginTop: 1 }}
> >
Check Availability Check Availability
</Button> </Button>

View file

@ -44,7 +44,8 @@ const AddStationLocationModal = ({
"City name must be at least 2 characters", "City name must be at least 2 characters",
}, },
})} })}
label="City Name" // label="City Name"
placeholder="Enter City Name"
fullWidth fullWidth
margin="normal" margin="normal"
error={!!errors.city} error={!!errors.city}

View file

@ -11,6 +11,7 @@ import {
Checkbox, Checkbox,
ListItemText, ListItemText,
InputLabel, InputLabel,
Chip,
} from "@mui/material"; } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
@ -20,7 +21,9 @@ import {
fetchVehicleBrands, fetchVehicleBrands,
vehicleList, vehicleList,
} from "../../redux/slices/VehicleSlice.ts"; // Adjust this import path accordingly } from "../../redux/slices/VehicleSlice.ts"; // Adjust this import path accordingly
import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css";// Assuming custom styled components import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; // Assuming custom styled components
import React from "react";
import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
export default function AddStationModal({ export default function AddStationModal({
open, open,
@ -157,6 +160,7 @@ export default function AddStationModal({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "100%", width: "100%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -166,6 +170,7 @@ export default function AddStationModal({
fullWidth fullWidth
placeholder="Enter Station Name" placeholder="Enter Station Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={ helperText={
errors.name ? errors.name.message : "" errors.name ? errors.name.message : ""
@ -191,6 +196,7 @@ export default function AddStationModal({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
width: "100%", width: "100%",
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -200,6 +206,8 @@ export default function AddStationModal({
fullWidth fullWidth
placeholder="Enter Charging Station Address" placeholder="Enter Charging Station Address"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.registeredAddress} error={!!errors.registeredAddress}
helperText={ helperText={
errors.registeredAddress errors.registeredAddress
@ -230,6 +238,8 @@ export default function AddStationModal({
fullWidth fullWidth
placeholder="Enter Total Slots" placeholder="Enter Total Slots"
size="small" size="small"
sx={{ marginTop: 1 }}
type="number" type="number"
error={!!errors.totalSlots} error={!!errors.totalSlots}
helperText={ helperText={
@ -251,6 +261,120 @@ export default function AddStationModal({
{/* Vehicle Brand Dropdown with Checkboxes */} {/* Vehicle Brand Dropdown with Checkboxes */}
<Box sx={{ display: "flex", gap: 2 }}> <Box sx={{ display: "flex", gap: 2 }}>
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
}}
>
<Typography
variant="body2"
fontWeight={500}
sx={{ mb: 1 }}
>
Vehicle Brand
</Typography>
<FormControl fullWidth size="small">
<Select
multiple
displayEmpty
sx={{ marginTop: 1 }}
value={selectedBrands}
onChange={handleBrandChange}
renderValue={(selected) => {
if (selected.length === 0) {
return (
<Typography color="text.secondary">
Choose Brands
</Typography>
);
}
const displayNames = (
selected as string[]
).slice(0, 1);
const moreCount =
(selected as string[]).length -
1;
return (
<Box
sx={{
display: "flex",
flexWrap: "wrap",
gap: 0.5,
}}
>
{displayNames.map((id) => {
const brand =
vehicleBrands.find(
(b) =>
b.id === id
);
return brand ? (
<Chip
key={id}
label={
brand.name
}
size="small"
sx={{
height: 24,
}}
/>
) : null;
})}
{moreCount > 0 && (
<Chip
label={`+${moreCount} more`}
size="small"
sx={{ height: 24 }}
/>
)}
</Box>
);
}}
MenuProps={{
PaperProps: {
style: {
maxHeight: 224,
},
},
}}
>
{vehicleBrands.length > 0 ? (
vehicleBrands.map((brand) => (
<MenuItem
key={brand.id}
value={brand.id}
>
<Checkbox
checked={selectedBrands.includes(
brand.id
)}
/>
<ListItemText
primary={brand.name}
/>
</MenuItem>
))
) : (
<MenuItem disabled>
No vehicle brands available
</MenuItem>
)}
</Select>
<FormHelperText>
{errors.vehicleBrand
? errors.vehicleBrand.message
: ""}
</FormHelperText>
</FormControl>
</Box>
{/* Replace the Vehicle Name Dropdown code with this */}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -258,145 +382,80 @@ export default function AddStationModal({
width: "100%", width: "100%",
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
Vehicle Brand variant="body2"
fontWeight={500}
sx={{ mb: 1 }}
>
Vehicle Name
</Typography> </Typography>
<FormControl fullWidth> <FormControl
<InputLabel>Choose Brands</InputLabel> fullWidth
size="small"
disabled={selectedBrands.length === 0}
>
<Select <Select
multiple multiple
value={selectedBrands} displayEmpty
onChange={handleBrandChange} sx={{ marginTop: 1 }}
value={selectedVehicles}
onChange={handleVehicleChange}
renderValue={(selected) => { renderValue={(selected) => {
const selectedArray = if (selected.length === 0) {
selected as string[]; return (
const displayNames = <Typography color="text.secondary">
selectedArray.slice(0, 1); // First 2 brands {selectedBrands.length ===
0
? "Select brand first"
: "Choose Vehicles"}
</Typography>
);
}
const displayNames = (
selected as string[]
).slice(0, 1);
const moreCount = const moreCount =
selectedArray.length - 1; (selected as string[]).length -
1;
return ( return (
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", flexWrap: "wrap",
gap: 1, gap: 0.5,
}} }}
> >
{displayNames.map( {displayNames.map(
(id, index) => { (name) => (
const brand = <Chip
vehicleBrands.find( key={name}
(b) => label={name}
b.id === size="small"
id sx={{
); height: 24,
return ( }}
<Typography />
key={index} )
variant="body2"
>
{brand
? brand.name
: ""}
</Typography>
);
}
)} )}
{moreCount > 0 && ( {moreCount > 0 && (
<Typography <Chip
variant="body2" label={`+${moreCount} more`}
color="textSecondary" size="small"
> sx={{ height: 24 }}
+{moreCount} more />
</Typography>
)} )}
</Box> </Box>
); );
}} }}
> MenuProps={{
{vehicleBrands.length > 0 ? ( PaperProps: {
vehicleBrands.map((brand) => ( style: {
<MenuItem maxHeight: 224,
key={brand.id} },
value={brand.id} },
>
<Checkbox
checked={selectedBrands.includes(
brand.id
)}
/>
<ListItemText
primary={brand.name}
/>
</MenuItem>
))
) : (
<MenuItem disabled>
No vehicle brands available
</MenuItem>
)}
</Select>
<FormHelperText>
{errors.vehicleBrand
? errors.vehicleBrand.message
: ""}
</FormHelperText>
</FormControl>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
}}
>
<Typography variant="body2" fontWeight={500}>
Vehicle Name
</Typography>
<FormControl fullWidth>
<InputLabel>Choose Vehicles</InputLabel>
<Select
multiple
value={selectedVehicles}
onChange={handleVehicleChange}
renderValue={(selected) => {
const selectedArray =
selected as string[];
const displayNames =
selectedArray.slice(0, 1); // First 2 vehicles
const moreCount =
selectedArray.length - 1;
return (
<Box
sx={{
display: "flex",
alignItems: "center",
gap: 1,
}}
>
{displayNames.map(
(name, index) => (
<Typography
key={index}
variant="body2"
>
{name}
</Typography>
)
)}
{moreCount > 0 && (
<Typography
variant="body2"
color="textSecondary"
>
+{moreCount} more
</Typography>
)}
</Box>
);
}} }}
> >
{filteredVehicles.length > 0 ? ( {filteredVehicles.length > 0 ? (

View file

@ -12,6 +12,7 @@ import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff"; import VisibilityOff from "@mui/icons-material/VisibilityOff";
import { useForm, Controller } from "react-hook-form"; import { useForm, Controller } from "react-hook-form";
import { CustomIconButton, CustomTextField } from "./styled.css.tsx"; import { CustomIconButton, CustomTextField } from "./styled.css.tsx";
import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
interface FormData { interface FormData {
name: string; name: string;
@ -109,6 +110,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -134,9 +136,11 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
<CustomTextField <CustomTextField
{...field} {...field}
required required
autoComplete="username"
placeholder="Enter User Name" placeholder="Enter User Name"
fullWidth fullWidth
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
/> />
@ -149,6 +153,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -172,6 +177,8 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
helperText={errors.email?.message} helperText={errors.email?.message}
type="email" type="email"
placeholder="Email" placeholder="Email"
autoComplete="new-email"
sx={{ marginTop: 1 }}
required required
fullWidth fullWidth
color={ color={
@ -190,6 +197,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -211,6 +219,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
{...field} {...field}
required required
placeholder="Enter Password" placeholder="Enter Password"
autoComplete="new-password"
type={ type={
showPassword ? "text" : "password" showPassword ? "text" : "password"
} }
@ -221,6 +230,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
: "primary" : "primary"
} }
size="small" size="small"
sx={{ marginTop: 1 }}
slotProps={{ slotProps={{
input: { input: {
endAdornment: ( endAdornment: (
@ -254,6 +264,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
flex: 1, flex: 1,
...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
@ -283,6 +294,7 @@ const AddUserModal: React.FC<AddUserModalProps> = ({
required required
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={errors.phone?.message} helperText={errors.phone?.message}
/> />

View file

@ -94,6 +94,8 @@ export default function AddVehicleModal({
fullWidth fullWidth
placeholder="Enter Company Name" placeholder="Enter Company Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.company} error={!!errors.company}
helperText={ helperText={
errors.company errors.company
@ -124,6 +126,8 @@ export default function AddVehicleModal({
fullWidth fullWidth
placeholder="Enter Vehicle Name" placeholder="Enter Vehicle Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={ helperText={
errors.name ? errors.name.message : "" errors.name ? errors.name.message : ""
@ -166,6 +170,8 @@ export default function AddVehicleModal({
fullWidth fullWidth
placeholder="Enter Model Name" placeholder="Enter Model Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.modelName} error={!!errors.modelName}
helperText={ helperText={
errors.modelName errors.modelName
@ -192,6 +198,8 @@ export default function AddVehicleModal({
fullWidth fullWidth
placeholder="Enter Charge Type" placeholder="Enter Charge Type"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.chargeType} error={!!errors.chargeType}
helperText={ helperText={
errors.chargeType errors.chargeType
@ -220,6 +228,8 @@ export default function AddVehicleModal({
fullWidth fullWidth
placeholder="Enter Image URL" placeholder="Enter Image URL"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.imageUrl} error={!!errors.imageUrl}
helperText={ helperText={
errors.imageUrl errors.imageUrl

View file

@ -9,8 +9,16 @@ import Typography from "@mui/material/Typography";
import MenuRoundedIcon from "@mui/icons-material/MenuRounded"; import MenuRoundedIcon from "@mui/icons-material/MenuRounded";
import DashboardRoundedIcon from "@mui/icons-material/DashboardRounded"; import DashboardRoundedIcon from "@mui/icons-material/DashboardRounded";
import ColorModeIconDropdown from "../../shared-theme/ColorModeIconDropdown"; import ColorModeIconDropdown from "../../shared-theme/ColorModeIconDropdown";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "../../redux/store/store";
import { fetchAdminProfile } from "../../redux/slices/profileSlice";
import NotificationsNoneIcon from "@mui/icons-material/NotificationsNone";
import InputBase from "@mui/material/InputBase";
import SearchIcon from "@mui/icons-material/Search";
import MenuButton from "../MenuButton"; import MenuButton from "../MenuButton";
import SideMenuMobile from "../SideMenuMobile"; import SideMenuMobile from "../SideMenuMobile";
import { Avatar } from "@mui/material";
import OptionsMenu from "../OptionsMenu";
const Toolbar = styled(MuiToolbar)({ const Toolbar = styled(MuiToolbar)({
width: "100%", width: "100%",
@ -30,18 +38,28 @@ const Toolbar = styled(MuiToolbar)({
export default function AppNavbar() { export default function AppNavbar() {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [showNotifications, setShowNotifications] = React.useState(false);
const toggleNotifications = () => {
setShowNotifications((prev) => !prev);
};
const dispatch = useDispatch<AppDispatch>();
const { user } = useSelector((state: RootState) => state?.profileReducer);
const toggleDrawer = (newOpen: boolean) => () => { const toggleDrawer = (newOpen: boolean) => () => {
setOpen(newOpen); setOpen(newOpen);
}; };
React.useEffect(() => {
dispatch(fetchAdminProfile());
}, [dispatch]);
return ( return (
<AppBar <AppBar
position="fixed" position="fixed"
sx={{ sx={{
display: { xs: "auto", md: "none" }, display: { xs: "auto", md: "none" },
boxShadow: 0, boxShadow: 0,
backgroundColor:"#1C1C1C", backgroundColor: "#1C1C1C",
backgroundImage: "none", backgroundImage: "none",
borderBottom: "1px solid", borderBottom: "1px solid",
borderColor: "divider", borderColor: "divider",
@ -64,13 +82,64 @@ export default function AppNavbar() {
sx={{ justifyContent: "center", mr: "auto" }} sx={{ justifyContent: "center", mr: "auto" }}
> >
<CustomIcon /> <CustomIcon />
<Typography {/* <Typography
variant="h4" variant="h4"
component="h1" component="h1"
sx={{ color: "#202020" }} sx={{ color: "#202020" }}
> >
Dashboard Dashboard
</Typography> */}
</Stack>
<Box
sx={{
// width: { xs: "100%", sm: "360px" },
height: "40px",
borderRadius: "8px",
border: "1px solid #424242",
display: {
md: "none",
xs: "flex",
sm: "flex",
lg: "none",
},
alignItems: "center",
padding: "0 12px",
}}
>
<SearchIcon sx={{ color: "#FFFFFF" }} />
<InputBase
sx={{
marginLeft: 1,
flex: 1,
color: "#FFFFFF",
fontSize: { xs: "12px", sm: "14px" },
}}
/>
</Box>
<Stack
direction="row"
spacing={2}
alignItems="center"
sx={{
pointer: "cursor",
display: { xs: "none", sm: "flex" }, // Hide on mobile, show on larger screens
}}
>
<NotificationsNoneIcon
sx={{ cursor: "pointer" }}
onClick={toggleNotifications}
/>
<Avatar
alt="User Avatar"
src="/avatar.png"
sx={{ width: 36, height: 36 }}
/>
<Typography variant="body1" sx={{ color: "#FFFFFF" }}>
{user?.name || "No Adminsss"}
</Typography> </Typography>
<OptionsMenu />
</Stack> </Stack>
{/* <ColorModeIconDropdown /> */} {/* <ColorModeIconDropdown /> */}
<MenuButton aria-label="menu" onClick={toggleDrawer(true)}> <MenuButton aria-label="menu" onClick={toggleDrawer(true)}>
@ -85,26 +154,29 @@ export default function AppNavbar() {
} }
export function CustomIcon() { export function CustomIcon() {
const [open, setOpen] = React.useState(true);
return ( return (
<Box <Box
sx={{ sx={{
width: "1.5rem",
height: "1.5rem",
bgcolor: "black",
borderRadius: "999px",
display: "flex", display: "flex",
flexDirection: "row",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
alignSelf: "center", pt: 2,
backgroundImage:
"linear-gradient(135deg, hsl(210, 98%, 60%) 0%, hsl(210, 100%, 35%) 100%)",
color: "hsla(210, 100%, 95%, 0.9)",
border: "1px solid",
borderColor: "hsl(210, 100%, 55%)",
boxShadow: "inset 0 2px 5px rgba(255, 255, 255, 0.3)",
}} }}
> >
<DashboardRoundedIcon color="inherit" sx={{ fontSize: "1rem" }} /> <img
src="/evLogo.png"
alt="Logo"
style={{
justifyContent: "center",
width: open ? "120px" : "60px",
height: "auto",
transition: "width 0.5s ease",
marginBottom: "10px",
}}
/>
</Box> </Box>
); );
} }

View file

@ -58,9 +58,13 @@ const StyledTableRow = styled(TableRow)(({ theme }) => ({
"&:nth-of-type(odd)": { "&:nth-of-type(odd)": {
backgroundColor: theme.palette.action.hover, backgroundColor: theme.palette.action.hover,
}, },
"&:nth-of-type(even)": {
backgroundColor: theme.palette.action.hover,
},
"& td, th": { "& td, th": {
borderColor: "#454545", // Applying border color to both td and th borderColor: "#454545", // Applying border color to both td and th
borderWidth: "1px", // Set border width to ensure it appears borderWidth: "1px", // Set border width to ensure it appears
borderBottom: "1px solid #454545",
}, },
})); }));
@ -227,11 +231,16 @@ const CustomTable: React.FC<CustomTableProps> = ({
return ( return (
<Box <Box
sx={{ sx={{
width: "calc(100% - 48px)", width: { xs: "100%", sm: "100%" },
margin: "0 auto", margin: "0 auto",
padding: "24px", padding: "24px",
backgroundColor: "#1C1C1C", backgroundColor: "#1C1C1C",
borderRadius: "12px", borderRadius: "12px",
overflowX: "auto",
boxSizing: "border-box",
// Ensure CustomTable doesn't affect layout above it
position: "relative",
zIndex: 1,
}} }}
> >
<Typography <Typography
@ -276,22 +285,24 @@ const CustomTable: React.FC<CustomTableProps> = ({
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: { xs: "column", sm: "column", md: "row" },
gap: { xs: "16px", sm: "16px", md: "0" },
marginTop: "16px", marginTop: "16px",
alignItems: "center", alignItems: { xs: "stretch", sm: "stretch", md: "center" },
width: "100%",
}} }}
> >
<TextField <TextField
variant="outlined" variant="outlined"
placeholder="Search" placeholder="Search"
sx={{ sx={{
width: "422px", width: { xs: "100%", sm: "100%", md: "380px" },
borderRadius: "12px", borderRadius: "12px",
input: { color: "#FFFFFF" }, input: { color: "#FFFFFF" },
backgroundColor: "#272727", backgroundColor: "#272727",
"& .MuiOutlinedInput-root": { "& .MuiOutlinedInput-root": {
borderRadius: "12px", borderRadius: "12px",
width: "422px", width: { xs: "100%", sm: "100%", md: "380px" },
height: "44px", height: "44px",
borderWidth: "1px", borderWidth: "1px",
padding: "14px 12px 14px 12px", padding: "14px 12px 14px 12px",
@ -319,6 +330,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
/> />
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -374,7 +386,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
)} )}
</Box> </Box>
<IconButton {/* <IconButton
sx={{ sx={{
width: "44px", width: "44px",
height: "44px", height: "44px",
@ -388,7 +400,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
}} }}
> >
<TuneIcon /> <TuneIcon />
</IconButton> </IconButton> */}
</Box> </Box>
{/* Table Section */} {/* Table Section */}
<TableContainer <TableContainer
@ -397,10 +409,21 @@ const CustomTable: React.FC<CustomTableProps> = ({
marginTop: "24px", marginTop: "24px",
backgroundColor: "#1C1C1C", backgroundColor: "#1C1C1C",
borderRadius: "12px", borderRadius: "12px",
overflow: "hidden", overflow: "auto",
maxWidth: "100%",
"&::-webkit-scrollbar": {
height: "3px",
},
"&::-webkit-scrollbar-track": {
background: "#1C1C1C",
},
"&::-webkit-scrollbar-thumb": {
background: "#52ACDF",
borderRadius: "4px",
},
}} }}
> >
<Table> <Table sx={{ minWidth: "750px", tableLayout: "auto" }}>
<TableHead <TableHead
sx={{ sx={{
backgroundColor: "#272727", backgroundColor: "#272727",
@ -408,6 +431,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
".css-1ex4ubw-MuiTableCell-root.MuiTableCell-head ": ".css-1ex4ubw-MuiTableCell-root.MuiTableCell-head ":
{ {
backgroundColor: "#272727", backgroundColor: "#272727",
borderBottom: "1px solid #454545",
}, },
}} }}
> >
@ -419,6 +443,16 @@ const CustomTable: React.FC<CustomTableProps> = ({
sx={{ sx={{
color: "#FFFFFF", color: "#FFFFFF",
fontWeight: "600", fontWeight: "600",
...(column.id === "action" && {
position: "sticky",
right: 0,
zIndex: 2,
backgroundColor: "#272727",
boxShadow:
"-5px 0 5px -2px rgba(0,0,0,0.15)",
borderBottom:
"1px solid #454545",
}),
}} }}
> >
{column.label} {column.label}
@ -433,51 +467,103 @@ const CustomTable: React.FC<CustomTableProps> = ({
}, },
}} }}
> >
{currentRows.map((row, rowIndex) => ( {/* This is where the modification starts */}
<StyledTableRow key={rowIndex}> {currentRows.length === 0 ? (
{columns.map((column) => ( <StyledTableRow>
<StyledTableCell <StyledTableCell
key={column.id} colSpan={columns.length}
sx={{ sx={{
color: "#D9D8D8", color: "#D9D8D8",
backgroundColor: "#272727", backgroundColor: "#272727",
}} textAlign: "center",
> padding: "32px 0",
{isImage(row[column.id]) ? ( }}
<img >
src={row[column.id]} {(() => {
alt="Row " switch (tableType) {
style={{ case "admin":
width: "50px", return "No admins found";
height: "50px", case "role":
objectFit: "cover", return "No roles found";
}} case "user":
/> return "No users found";
) : column.id !== "action" ? ( case "manager":
row[column.id] return "No managers found";
) : ( case "vehicle":
<CustomIconButton return "No vehicles found";
onClick={(e) => { case "station":
handleClick(e, row); return "No charging stations found";
setRowData(row); // Store the selected row case "external-station":
}} return "No charging stations found";
sx={{ case "booking":
padding: 0, return "No bookings found";
minWidth: 0, case "slots":
width: "auto", return "No slots found";
height: "auto", case "all-available-slots":
color: "#FFFFFF", return "No available slots found";
}} default:
> return "No data available";
<MoreHorizRoundedIcon }
sx={{ fontSize: "24px" }} })()}
/> </StyledTableCell>
</CustomIconButton>
)}
</StyledTableCell>
))}
</StyledTableRow> </StyledTableRow>
))} ) : (
currentRows.map((row, rowIndex) => (
<StyledTableRow key={rowIndex}>
{columns.map((column) => (
<StyledTableCell
key={column.id}
sx={{
color: "#D9D8D8",
backgroundColor: "#272727",
...(column.id === "action" && {
position: "sticky",
right: 0,
zIndex: 2,
backgroundColor: "#272727",
boxShadow:
"-5px 0 5px -2px rgba(0,0,0,0.15)",
}),
}}
>
{isImage(row[column.id]) ? (
<img
src={row[column.id]}
alt="Row "
style={{
width: "50px",
height: "50px",
objectFit: "cover",
}}
/>
) : column.id !== "action" ? (
row[column.id]
) : (
<CustomIconButton
onClick={(e) => {
handleClick(e, row);
setRowData(row);
}}
sx={{
padding: 0,
minWidth: 0,
width: "auto",
height: "auto",
color: "#FFFFFF",
}}
>
<MoreHorizRoundedIcon
sx={{
fontSize: "24px",
}}
/>
</CustomIconButton>
)}
</StyledTableCell>
))}
</StyledTableRow>
))
)}
</TableBody> </TableBody>
</Table> </Table>
</TableContainer> </TableContainer>

View file

@ -171,6 +171,8 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
fullWidth fullWidth
placeholder="Enter Manager Name" placeholder="Enter Manager Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
/> />
@ -193,6 +195,8 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
fullWidth fullWidth
placeholder="Enter Email" placeholder="Enter Email"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.email} error={!!errors.email}
helperText={errors.email?.message} helperText={errors.email?.message}
/> />
@ -229,6 +233,8 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
fullWidth fullWidth
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={errors.phone?.message} helperText={errors.phone?.message}
/> />
@ -249,6 +255,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
borderRadius: "8px", borderRadius: "8px",
width: "117px", width: "117px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#439BC1" },
whiteSpace: "pre",
}} }}
disabled={loading} disabled={loading}
> >

View file

@ -20,10 +20,7 @@ import {
fetchVehicleBrands, fetchVehicleBrands,
vehicleList, vehicleList,
} from "../../redux/slices/VehicleSlice"; } from "../../redux/slices/VehicleSlice";
import { import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; // Assuming custom styled components
CustomIconButton,
CustomTextField,
} from "../AddUserModal/styled.css"; // Assuming custom styled components
interface FormData { interface FormData {
name: string; name: string;
@ -81,11 +78,33 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
useEffect(() => { useEffect(() => {
dispatch(fetchVehicleBrands()); dispatch(fetchVehicleBrands());
dispatch(vehicleList()); // Fetch vehicles when the component mounts dispatch(vehicleList());
}, [dispatch]); }, [dispatch]);
useEffect(() => { useEffect(() => {
if (editRow) { if (editRow) {
// Determine the brand based on the first vehicle's company
const firstVehicle = vehicles.find(
(vehicle) =>
editRow.allowedCarIds &&
editRow.allowedCarIds.includes(vehicle.name)
);
const brandId = firstVehicle ? firstVehicle.company : "";
setSelectedBrands(brandId);
// Populate selected vehicles
const vehicleNames = vehicles
.filter(
(vehicle) =>
editRow.allowedCarIds &&
editRow.allowedCarIds.includes(vehicle.name)
)
.map((vehicle) => vehicle.name);
setSelectedVehicles(vehicleNames);
// Set form values
setValue("name", editRow.name); setValue("name", editRow.name);
setValue("registeredAddress", editRow.registeredAddress); setValue("registeredAddress", editRow.registeredAddress);
setValue("totalSlots", editRow.totalSlots); setValue("totalSlots", editRow.totalSlots);
@ -94,15 +113,13 @@ 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 = editRow?.allowedCarIds const brands = editRow?.allowedCarIds
? vehicles ? vehicles
.filter((vehicle) => .filter((vehicle) =>
editRow.allowedCarIds.includes(vehicle.id) editRow.allowedCarIds.includes(vehicle.id)
) )
.map((vehicle) => vehicle.company) .map((vehicle) => vehicle.company)
: []; : [];
setSelectedBrands(brands); setSelectedBrands(brands);
} else { } else {
@ -112,13 +129,11 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
} }
}, [editRow, setValue, reset, vehicles]); }, [editRow, setValue, reset, vehicles]);
// Filter vehicles based on selected brands // Filter vehicles based on selected brands
const filteredVehicles = vehicles.filter((vehicle) => const filteredVehicles = vehicles.filter((vehicle) =>
selectedBrands.includes(vehicle.company) selectedBrands.includes(vehicle.company)
); );
// Handle changes in vehicle brand selection // Handle changes in vehicle brand selection
const handleBrandChange = ( const handleBrandChange = (
event: React.ChangeEvent<{ value: unknown }> event: React.ChangeEvent<{ value: unknown }>
@ -133,37 +148,35 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
setSelectedVehicles(filtered.map((v) => v.name)); // Automatically select vehicles for the selected brands setSelectedVehicles(filtered.map((v) => v.name)); // Automatically select vehicles for the selected brands
}; };
// Handle changes in vehicle selection // Handle changes in vehicle selection
const handleCheckboxChange = ( const handleCheckboxChange = (
event: React.ChangeEvent<{ value: unknown }> event: React.ChangeEvent<{ value: unknown }>
) => { ) => {
const value = event.target.value as string[]; const value = event.target.value as string[];
setSelectedVehicles(value); setSelectedVehicles(value);
setValue("allowedCarIds", value); // Update allowedCarIds in form state setValue("allowedCarIds", value);
}; };
const onSubmit = (data: FormData) => { const onSubmit = (data: FormData) => {
const vehicleIds = vehicles const vehicleIds = vehicles
.filter((vehicle) => selectedVehicles.includes(vehicle.name)) .filter((vehicle) => selectedVehicles.includes(vehicle.name))
.map((vehicle) => Number(vehicle.id)); .map((vehicle) => Number(vehicle.id));
handleUpdate( handleUpdate(
editRow.id, editRow.id,
data.name, data.name,
data.registeredAddress, data.registeredAddress,
data.totalSlots, data.totalSlots,
vehicleIds vehicleIds
); );
handleClose(); handleClose();
reset(); reset();
setSelectedBrands([]); // Reset brands after submit setSelectedBrands([]); // Reset brands after submit
setSelectedVehicles([]); // Reset selected vehicles setSelectedVehicles([]); // Reset selected vehicles
}; };
console.log("editRow:", editRow); console.log("editRow:", editRow);
return ( return (
<Modal <Modal
open={open} open={open}
@ -236,6 +249,7 @@ const onSubmit = (data: FormData) => {
fullWidth fullWidth
placeholder="Enter Station Name" placeholder="Enter Station Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={ helperText={
errors.name errors.name
@ -269,6 +283,7 @@ const onSubmit = (data: FormData) => {
fullWidth fullWidth
placeholder="Enter Registered Address" placeholder="Enter Registered Address"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.registeredAddress} error={!!errors.registeredAddress}
helperText={ helperText={
errors.registeredAddress errors.registeredAddress
@ -307,6 +322,7 @@ const onSubmit = (data: FormData) => {
fullWidth fullWidth
placeholder="Enter Total Slots" placeholder="Enter Total Slots"
size="small" size="small"
sx={{ marginTop: 1 }}
type="number" type="number"
error={!!errors.totalSlots} error={!!errors.totalSlots}
helperText={ helperText={
@ -336,6 +352,7 @@ const onSubmit = (data: FormData) => {
<InputLabel>Choose Brand</InputLabel> <InputLabel>Choose Brand</InputLabel>
<Select <Select
multiple multiple
sx={{ marginTop: 1 }}
value={selectedBrands} value={selectedBrands}
onChange={handleBrandChange} onChange={handleBrandChange}
label="Choose Brands" label="Choose Brands"
@ -426,6 +443,7 @@ const onSubmit = (data: FormData) => {
<InputLabel>Choose Vehicles</InputLabel> <InputLabel>Choose Vehicles</InputLabel>
<Select <Select
multiple multiple
sx={{ marginTop: 1 }}
value={selectedVehicles} value={selectedVehicles}
onChange={handleCheckboxChange} onChange={handleCheckboxChange}
renderValue={(selected) => { renderValue={(selected) => {

View file

@ -133,6 +133,7 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
fullWidth fullWidth
placeholder="Enter Full Name" placeholder="Enter Full Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
/> />
@ -163,6 +164,7 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
fullWidth fullWidth
placeholder="Enter Email" placeholder="Enter Email"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.email} error={!!errors.email}
helperText={errors.email?.message} helperText={errors.email?.message}
/> />
@ -199,6 +201,7 @@ const EditUserModal: React.FC<EditUserModalProps> = ({
fullWidth fullWidth
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={errors.phone?.message} helperText={errors.phone?.message}
/> />

View file

@ -174,6 +174,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
fullWidth fullWidth
placeholder="Enter Vehicle Name" placeholder="Enter Vehicle Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
@ -206,6 +207,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
fullWidth fullWidth
placeholder="Enter Company Name" placeholder="Enter Company Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.company} error={!!errors.company}
helperText={errors.company?.message} helperText={errors.company?.message}
/> />
@ -240,6 +242,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
fullWidth fullWidth
placeholder="Enter Model Name" placeholder="Enter Model Name"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.modelName} error={!!errors.modelName}
helperText={errors.modelName?.message} helperText={errors.modelName?.message}
/> />
@ -271,6 +274,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
fullWidth fullWidth
placeholder="Enter Charge Type" placeholder="Enter Charge Type"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.chargeType} error={!!errors.chargeType}
helperText={errors.chargeType?.message} helperText={errors.chargeType?.message}
/> />
@ -300,6 +304,7 @@ const EditVehicleModal: React.FC<EditVehicleModalProps> = ({
fullWidth fullWidth
placeholder="Enter Image URL" placeholder="Enter Image URL"
size="small" size="small"
sx={{ marginTop: 1 }}
error={!!errors.imageUrl} error={!!errors.imageUrl}
helperText={errors.imageUrl?.message} helperText={errors.imageUrl?.message}
/> />

View file

@ -26,16 +26,25 @@ export default function Header() {
}, [dispatch]); }, [dispatch]);
return ( return (
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
height: "84px", height: "84px",
backgroundColor: "#1C1C1C", minHeight: "84px",
padding: { xs: "20px 12px", sm: "20px 24px" }, maxHeight: "84px",
display: "flex", backgroundColor: "#1C1C1C",
alignItems: "center", padding: { xs: "20px 12px", sm: "20px 24px" },
justifyContent: "space-between", display: {
flexDirection: { xs: "column", sm: "row" }, xs: "none",
}} md: "flex",
},
marginTop: { xs: "0px", sm: "0px" },
alignItems: "center",
justifyContent: "space-between",
flexDirection: { xs: "column", sm: "row" },
boxSizing: "border-box",
overflowX: "hidden",
flex: "0 0 84px",
}}
> >
<Stack <Stack
direction="row" direction="row"
@ -45,14 +54,17 @@ export default function Header() {
sx={{ sx={{
width: "100%", width: "100%",
justifyContent: { xs: "center", sm: "flex-end" }, justifyContent: { xs: "center", sm: "flex-end" },
marginTop: { xs: 2, sm: 0 }, marginTop: { xs: 0, sm: 0 }, // Remove top margin on mobile
flexWrap: { xs: "wrap", sm: "nowrap" },
maxHeight: "100%", // Ensure content doesn't push height
overflow: "hidden", // Prevent overflow
}} }}
> >
{/* Search Bar */} {/* Search Bar */}
<Box <Box
sx={{ sx={{
// width: { xs: "100%", sm: "360px" }, // width: { xs: "100%", sm: "360px" },
height: "44px", height: "40px",
borderRadius: "8px", borderRadius: "8px",
border: "1px solid #424242", border: "1px solid #424242",
@ -78,17 +90,21 @@ export default function Header() {
spacing={2} spacing={2}
alignItems="center" alignItems="center"
sx={{ sx={{
pointer: "cursor",
display: { xs: "none", sm: "flex" }, // Hide on mobile, show on larger screens display: { xs: "none", sm: "flex" }, // Hide on mobile, show on larger screens
}} }}
> >
<NotificationsNoneIcon onClick={toggleNotifications} /> <NotificationsNoneIcon
sx={{ cursor: "pointer" }}
onClick={toggleNotifications}
/>
<Avatar <Avatar
alt="User Avatar" alt="User Avatar"
src="/avatar.png" src="/avatar.png"
sx={{ width: 36, height: 36 }} sx={{ width: 36, height: 36 }}
/> />
<Typography variant="body1" sx={{ color: "#FFFFFF" }}> <Typography variant="body1" sx={{ color: "#FFFFFF" }}>
{user?.name || "No Admin"} {user?.name || "No Adminsss"}
</Typography> </Typography>
<OptionsMenu /> <OptionsMenu />

View file

@ -10,6 +10,7 @@ import useMediaQuery from "@mui/material/useMediaQuery";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "../../redux/store/store"; import { AppDispatch, RootState } from "../../redux/store/store";
import { fetchDashboardData } from "../../redux/slices/dashboardSlice"; import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
import { Box } from "@mui/material";
function AreaGradient({ color, id }: { color: string; id: string }) { function AreaGradient({ color, id }: { color: string; id: string }) {
return ( return (
@ -159,12 +160,13 @@ export default function LineChartCard() {
</div> </div>
{/* Line Chart */} {/* Line Chart */}
<Box sx={{ mt: 7.5 }}>
<LineChart <LineChart
colors={[theme.palette.primary.main]} colors={[theme.palette.primary.main]}
xAxis={[ xAxis={[
{ {
scaleType: "point", scaleType: "point",
data: chartData.map((data) => data.label), // Use intervals as x-axis labels data: chartData.map((data) => data.label),
}, },
]} ]}
series={[ series={[
@ -173,7 +175,7 @@ export default function LineChartCard() {
showMark: false, showMark: false,
curve: "linear", curve: "linear",
area: true, area: true,
data: chartData.map((data) => data.value), // Use interval data for y-axis data: chartData.map((data) => data.value),
color: theme.palette.primary.main, color: theme.palette.primary.main,
}, },
]} ]}
@ -191,6 +193,7 @@ export default function LineChartCard() {
id="totalBookings" id="totalBookings"
/> />
</LineChart> </LineChart>
</Box>
</CardContent> </CardContent>
</Card> </Card>
); );

View file

@ -12,43 +12,37 @@ import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
import { useEffect } from "react"; import { useEffect } from "react";
export default function MainGrid() { export default function MainGrid() {
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
const { const {
totalAdmins, totalAdmins,
totalManagers, totalManagers,
totalUsers, totalUsers,
totalStations, totalStations,
loading, loading,
error, error,
} = useSelector((state: RootState) => state.dashboardReducer); } = useSelector((state: RootState) => state.dashboardReducer);
const staticData = {
const staticData = {
totalAdmins: 86, totalAdmins: 86,
totalManagers: 12, totalManagers: 12,
totalUsers: 24, totalUsers: 24,
totalStations: 8, totalStations: 8,
}; };
useEffect(() => { useEffect(() => {
dispatch(fetchDashboardData());
dispatch(fetchDashboardData());
}, [dispatch]); }, [dispatch]);
const data = const data = { totalAdmins, totalManagers, totalUsers, totalStations };
{ totalAdmins, totalManagers, totalUsers, totalStations }
const statCards = [ const statCards = [
{ title: "Total Admins", value: data.totalAdmins }, { title: "Total Admins", value: data.totalAdmins },
{ title: "Total Managers", value: data.totalManagers }, { title: "Total Managers", value: data.totalManagers },
{ title: "Total Users", value: data.totalUsers }, { title: "Total Users", value: data.totalUsers },
{ title: "Total Stations", value: data.totalStations }, { title: "Total Stations", value: data.totalStations },
]; ];
return ( return (
<Box <Box
sx={{ sx={{
width: "100%", width: "100%",
@ -86,5 +80,5 @@ export default function MainGrid() {
</Grid> </Grid>
</Grid> </Grid>
</Box> </Box>
); );
} }

View file

@ -17,7 +17,7 @@ export default function MenuButton({
invisible={!showBadge} invisible={!showBadge}
sx={{ [`& .${badgeClasses.badge}`]: { right: 2, top: 2 } }} sx={{ [`& .${badgeClasses.badge}`]: { right: 2, top: 2 } }}
> >
<IconButton size="small" {...props} /> <IconButton sx={{ marginRight: "60px" }} size="small" {...props} />
</Badge> </Badge>
); );
} }

View file

@ -144,7 +144,9 @@ export default function MenuContent({ hidden }: PropType) {
fontSize: "16px", fontSize: "16px",
letterSpacing: "0%", letterSpacing: "0%",
lineHeight: "100%", lineHeight: "100%",
color: "#D9D8D8", whiteSpace: "pre",
color: "#FAFAFA",
marginTop: "5px",
}, },
}} }}
primary={item.text} primary={item.text}

View file

@ -12,10 +12,10 @@ import { useEffect } from "react";
import { fetchDashboardData } from "../../redux/slices/dashboardSlice"; import { fetchDashboardData } from "../../redux/slices/dashboardSlice";
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 = [
@ -26,17 +26,17 @@ const colorPalette = [
// ]; // ];
export default function ResourcePieChart() { export default function ResourcePieChart() {
const theme = useTheme(); const theme = useTheme();
const isXsScreen = useMediaQuery(theme.breakpoints.down("sm")); const isXsScreen = useMediaQuery(theme.breakpoints.down("sm"));
const isSmScreen = useMediaQuery(theme.breakpoints.between("sm", "md")); const isSmScreen = useMediaQuery(theme.breakpoints.between("sm", "md"));
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
// // Fetch role and carPortCounts from Redux state // // Fetch role and carPortCounts from Redux state
// const {user} = useSelector((state: RootState) => state.profileReducer); // Assuming user role is stored in Redux // const {user} = useSelector((state: RootState) => state.profileReducer); // Assuming user role is stored in Redux
const { carPortCounts } = useSelector( const { carPortCounts } = useSelector(
(state: RootState) => state.dashboardReducer (state: RootState) => state.dashboardReducer
); );
console.log("first",carPortCounts) console.log("first", carPortCounts);
// Static data for non-superadmin roles // Static data for non-superadmin roles
// const staticCarPorts = [ // const staticCarPorts = [
// { carPort: "240V", count: 5 }, // { carPort: "240V", count: 5 },
@ -45,52 +45,50 @@ export default function ResourcePieChart() {
// { carPort: "Other", count: 7 }, // { carPort: "Other", count: 7 },
// ]; // ];
useEffect(() => { useEffect(() => {
dispatch(fetchDashboardData()); dispatch(fetchDashboardData());
}, [dispatch]);
}, [dispatch]);
// console.log("Raw CarPortCounts from API:", carPortCounts); // console.log("Raw CarPortCounts from API:", carPortCounts);
const dataToDisplay =carPortCounts const dataToDisplay = carPortCounts;
// const dataToDisplay = // const dataToDisplay =
// user?.userType === "superadmin" // user?.userType === "superadmin"
// ? carPortCounts.filter((entry) => entry.count > 0) // Exclude zero counts // ? carPortCounts.filter((entry) => entry.count > 0) // Exclude zero counts
// : staticCarPorts.filter((entry) => entry.count > 0); // : staticCarPorts.filter((entry) => entry.count > 0);
// console.log("Filtered Data to Display:", dataToDisplay); // console.log("Filtered Data to Display:", dataToDisplay);
const getChartDimensions = () => { const getChartDimensions = () => {
if (isXsScreen) { if (isXsScreen) {
return { return {
height: 240, height: 240,
width: 240, width: 240,
innerRadius: 40, innerRadius: 40,
outerRadius: 80, outerRadius: 80,
margin: { left: 20, right: 20, top: 40, bottom: 40 } margin: { left: 20, right: 20, top: 40, bottom: 40 },
}; };
} else if (isSmScreen) { } else if (isSmScreen) {
return { return {
height: 260, height: 260,
width: 260, width: 260,
innerRadius: 50, innerRadius: 50,
outerRadius: 90, outerRadius: 90,
margin: { left: 40, right: 40, top: 60, bottom: 60 } margin: { left: 40, right: 40, top: 60, bottom: 60 },
}; };
} else { } else {
return { return {
height: 350, height: 350,
width: 350, width: 350,
innerRadius: 55, innerRadius: 55,
outerRadius: 110, outerRadius: 110,
margin: { left: 60, right: 80, top: 80, bottom: 80 } margin: { left: 60, right: 80, top: 80, bottom: 80 },
}; };
} }
}; };
const dimensions = getChartDimensions(); const dimensions = getChartDimensions();
return ( return (
<Card <Card
variant="outlined" variant="outlined"
sx={{ sx={{
@ -162,7 +160,6 @@ const dataToDisplay =carPortCounts
legend: { hidden: true }, legend: { hidden: true },
}} }}
/> />
<Stack <Stack
spacing={1} spacing={1}
sx={{ sx={{
@ -170,6 +167,8 @@ const dataToDisplay =carPortCounts
ml: { xs: 0, sm: 2 }, ml: { xs: 0, sm: 2 },
}} }}
> >
<Typography sx={{whiteSpace: "pre"}}>Car Port Types:</Typography>
{dataToDisplay.map((entry, index) => ( {dataToDisplay.map((entry, index) => (
<Stack <Stack
key={index} key={index}
@ -207,5 +206,5 @@ const dataToDisplay =carPortCounts
</Box> </Box>
</CardContent> </CardContent>
</Card> </Card>
); );
} }

View file

@ -14,6 +14,7 @@ import CardAlert from "../CardAlert/CardAlert";
import { AppDispatch, RootState } from "../../redux/store/store"; import { AppDispatch, RootState } from "../../redux/store/store";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { fetchAdminProfile } from "../../redux/slices/profileSlice"; import { fetchAdminProfile } from "../../redux/slices/profileSlice";
import Logout from "../LogOutFunction/LogOutFunction";
interface SideMenuMobileProps { interface SideMenuMobileProps {
open: boolean | undefined; open: boolean | undefined;
@ -25,6 +26,7 @@ export default function SideMenuMobile({
toggleDrawer, toggleDrawer,
}: SideMenuMobileProps) { }: SideMenuMobileProps) {
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
const [logoutModal, setLogoutModal] = React.useState<boolean>(false);
const { user } = useSelector((state: RootState) => state?.profileReducer); const { user } = useSelector((state: RootState) => state?.profileReducer);
// React.useEffect(() => { // React.useEffect(() => {
// dispatch(fetchAdminProfile()); // dispatch(fetchAdminProfile());
@ -79,9 +81,18 @@ export default function SideMenuMobile({
variant="outlined" variant="outlined"
fullWidth fullWidth
startIcon={<LogoutRoundedIcon />} startIcon={<LogoutRoundedIcon />}
onClick={(e) => {
e.stopPropagation();
setLogoutModal(true);
}}
sx={{ color: "red" }}
> >
Logout Logout
</Button> </Button>
<Logout
setLogoutModal={setLogoutModal}
logoutModal={logoutModal}
/>
</Stack> </Stack>
</Stack> </Stack>
</Drawer> </Drawer>

View file

@ -16,9 +16,11 @@ const DashboardLayout: React.FC<LayoutProps> = ({ customStyles }) => {
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
height: "auto", // height: "auto",
flexDirection: { xs: "column", md: "row" }, flexDirection: { xs: "column", md: "row" },
width: "100%", width: "100%",
height: "100vh", // Full height from root, not auto
overflow: "hidden",
margin: 0, margin: 0,
padding: 0, padding: 0,
}} }}
@ -43,29 +45,32 @@ const DashboardLayout: React.FC<LayoutProps> = ({ customStyles }) => {
flexDirection: "column", flexDirection: "column",
height: "100vh", height: "100vh",
flexGrow: 1, flexGrow: 1,
// backgroundColor: theme.vars
// ? `rgba(${theme.vars.palette.background.defaultChannel} / 1)`
// : theme.palette.background.default,
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
overflow: "auto", overflow: "auto",
overflowX: "hidden",
...customStyles, ...customStyles,
mt: { xs: 8, md: 0 }, mt: { xs: 8, md: 0 },
padding: 0, padding: 0,
})} })}
> >
<Box sx={{ height: "84px", flex: "0 0 84px" }}>
<Header />
</Box>
<Stack <Stack
spacing={2} spacing={2}
sx={{ sx={{
padding: "30px",
display: "flex", display: "flex",
flex: 1, flex: 1,
justifyItems: "center", justifyItems: "center",
alignItems: "center", alignItems: "center",
mx: 3, // mx: { xs: 1, sm: 3 },
pb: 5, // pb: 5,
mt: { xs: 3, md: 0 }, mt: { xs: 3, md: 0 },
width: "100%",
boxSizing: "border-box",
}} }}
> >
<Header />
<Outlet /> <Outlet />
</Stack> </Stack>
</Box> </Box>

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";
import { autofillFix } from "../../../shared-theme/customizations/autoFill.tsx";
interface ILoginForm { interface ILoginForm {
email: string; email: string;
@ -50,14 +51,14 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
}; };
const togglePasswordVisibility = (e: React.MouseEvent) => { const togglePasswordVisibility = (e: React.MouseEvent) => {
e.preventDefault(); 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(); const isValid = await trigger();
if (!isValid) { if (!isValid) {
return; return;
} }
try { try {
const response = await dispatch(loginUser(data)).unwrap(); const response = await dispatch(loginUser(data)).unwrap();
@ -73,7 +74,6 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<AppTheme {...props}> <AppTheme {...props}>
<SignInContainer direction="column" justifyContent="space-between"> <SignInContainer direction="column" justifyContent="space-between">
<Grid container sx={{ minHeight: "100vh" }}> <Grid container sx={{ minHeight: "100vh" }}>
<Grid <Grid
item item
xs={0} xs={0}
@ -82,11 +82,10 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
sx={{ sx={{
background: `url('/Login.svg') center/cover no-repeat`, background: `url('/Login.svg') center/cover no-repeat`,
backgroundSize: "cover", backgroundSize: "cover",
display: { xs: "none", md: "block" }, display: { xs: "none", md: "block" },
position: "relative", position: "relative",
}} }}
> >
<Box <Box
sx={{ sx={{
position: "absolute", position: "absolute",
@ -122,7 +121,6 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
position: "relative", position: "relative",
}} }}
> >
<Box <Box
sx={{ sx={{
display: { xs: "flex", md: "none" }, display: { xs: "flex", md: "none" },
@ -164,7 +162,12 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<Card <Card
variant="outlined" variant="outlined"
sx={{ sx={{
width: { xs: "100%", sm: "90%", md: "90%", lg: "408px" }, width: {
xs: "100%",
sm: "90%",
md: "90%",
lg: "408px",
},
maxWidth: "408px", maxWidth: "408px",
minHeight: { xs: "auto", md: "428px" }, minHeight: { xs: "auto", md: "428px" },
padding: { xs: "16px", sm: "20px", md: "24px" }, padding: { xs: "16px", sm: "20px", md: "24px" },
@ -201,7 +204,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
variant="subtitle2" variant="subtitle2"
sx={{ sx={{
textAlign: "center", textAlign: "center",
color: "white", color: "#D9D8D8",
fontSize: { xs: "14px", md: "16px" }, fontSize: { xs: "14px", md: "16px" },
mb: 1, mb: 1,
}} }}
@ -214,12 +217,14 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<FormLabel <FormLabel
htmlFor="email" htmlFor="email"
sx={{ sx={{
borderRadius: "8px",
fontSize: { fontSize: {
xs: "0.875rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
}, },
color: "white", color: "white",
mb: 0.5, mb: 0.5,
...autofillFix,
}} }}
> >
Email Email
@ -258,7 +263,10 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
} }
InputProps={{ InputProps={{
sx: { sx: {
height: { xs: "45px", md: "50px" }, height: {
xs: "45px",
md: "50px",
},
alignItems: "center", alignItems: "center",
backgroundColor: backgroundColor:
"#1E1F1F", "#1E1F1F",
@ -269,7 +277,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
{ {
backgroundColor: backgroundColor:
"#1E1F1F", "#1E1F1F",
borderRadius: "4px", borderRadius: "8px",
"& fieldset": { "& fieldset": {
borderColor: borderColor:
"#4b5255", "#4b5255",
@ -302,6 +310,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
fontFamily: fontFamily:
"Gilroy, sans-serif", "Gilroy, sans-serif",
}, },
...autofillFix,
}} }}
/> />
)} )}
@ -313,6 +322,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
<FormLabel <FormLabel
htmlFor="password" htmlFor="password"
sx={{ sx={{
borderRadius: "8px",
fontSize: { fontSize: {
xs: "0.875rem", xs: "0.875rem",
sm: "1rem", sm: "1rem",
@ -350,13 +360,13 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
} }
name="password" name="password"
placeholder="Password" placeholder="Password"
autoComplete="current-password"
type={ type={
showPassword showPassword
? "text" ? "text"
: "password" : "password"
} }
id="password" id="password"
autoComplete="current-password"
required required
fullWidth fullWidth
variant="outlined" variant="outlined"
@ -367,15 +377,20 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
} }
InputProps={{ InputProps={{
sx: { sx: {
height: { xs: "45px", md: "50px" }, height: {
xs: "45px",
md: "50px",
},
...autofillFix,
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
<CustomIconButton <CustomIconButton
aria-label="toggle password visibility" aria-label="toggle password visibility"
onClick={ onClick={
togglePasswordVisibility togglePasswordVisibility
} } // Only the button triggers visibility toggle
edge="end" edge="end"
> >
{showPassword ? ( {showPassword ? (
@ -392,7 +407,7 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
{ {
backgroundColor: backgroundColor:
"#1E1F1F", "#1E1F1F",
borderRadius: "4px", borderRadius: "8px",
"& fieldset": { "& fieldset": {
borderColor: borderColor:
"#4b5255", "#4b5255",
@ -468,11 +483,11 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
label={ label={
<Typography <Typography
sx={{ sx={{
fontSize: { fontSize: {
xs: "0.75rem", xs: "0.75rem",
sm: "0.875rem", sm: "0.875rem",
md: "1rem" md: "1rem",
} },
}} }}
> >
Remember me Remember me
@ -489,21 +504,21 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
alignSelf: "center", alignSelf: "center",
color: "#01579b", color: "#01579b",
textDecoration: "none", textDecoration: "none",
fontSize: { fontSize: {
xs: "0.75rem", xs: "0.75rem",
sm: "0.875rem", sm: "0.875rem",
md: "1rem" md: "1rem",
}, },
}} }}
> >
Forgot password? Forgot password?
</Link> </Link>
</Box> </Box>
<ForgotPassword {/* <ForgotPassword
open={open} open={open}
handleClose={handleClose} handleClose={handleClose}
/> /> */}
{/* Login Button */} {/* Login Button */}
<Button <Button
type="submit" type="submit"
@ -518,7 +533,10 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
}, },
padding: { xs: "8px 0", md: "10px 0" }, padding: { xs: "8px 0", md: "10px 0" },
mt: { xs: 2, md: 3 }, mt: { xs: 2, md: 3 },
fontSize: { xs: "0.875rem", md: "1rem" }, fontSize: {
xs: "0.875rem",
md: "1rem",
},
}} }}
> >
Login Login
@ -530,4 +548,4 @@ export default function Login(props: { disableCustomTheme?: boolean }) {
</SignInContainer> </SignInContainer>
</AppTheme> </AppTheme>
); );
} }

View file

@ -52,48 +52,40 @@ const ProfilePage = () => {
</Typography> </Typography>
<Card <Card
sx={{ sx={{
width: "1132px", borderRadius: 2,
height: "331px", p: { xs: 2, sm: 3 },
gap: "24px", mx: "auto",
borderRadius: "12px",
padding: "16px",
maxWidth: "100%",
margin: "0 auto",
backgroundColor: "#1C1C1C", backgroundColor: "#1C1C1C",
}} }}
// sx={{
// width: "1132px",
// height: "331px",
// gap: "24px",
// borderRadius: "12px",
// padding: "16px",
// maxWidth: "100%",
// margin: "0 auto",
// backgroundColor: "#1C1C1C",
// }}
> >
<CardContent> <CardContent>
<Stack direction="column" spacing={2}> <Stack direction="column" spacing={2}>
<Stack <Stack direction="row" spacing={2} alignItems="center">
direction="row"
spacing={1.5}
alignItems="center"
>
<Avatar <Avatar
alt="User Avatar" alt="User Avatar"
src="/avatar.png" src="/avatar.png"
sx={{ width: "60px", height: "60px" }} sx={{ width: 60, height: 60 }}
/> />
<Box> <Box>
<Typography <Typography
variant="body1" variant="body1"
width="1028px" sx={{ color: "#FFFFFF", fontWeight: 500 }}
height="24px"
fontWeight={500}
fontSize={"20px"}
lineHeight={"100%"}
sx={{ color: "#FFFFFF" }}
> >
{user?.name || "No Admin"} {user?.name || "No Admin"}
</Typography> </Typography>
<Typography <Typography
variant="body2" variant="body2"
color="#D9D8D8" sx={{ color: "#D9D8D8" }}
fontWeight={400}
fontSize={"16px"}
lineHeight={"100%"}
width="46px"
height="19px"
> >
{user?.userType || "N/A"} {user?.userType || "N/A"}
</Typography> </Typography>
@ -105,18 +97,13 @@ const ProfilePage = () => {
/> />
<Stack <Stack
direction="row" direction={{ xs: "column", sm: "row" }}
justifyContent="space-between" justifyContent="space-between"
alignItems="center" alignItems={{ xs: "flex-start", sm: "center" }}
> >
<Typography <Typography
variant="body1" variant="body1"
width="1048px" sx={{ color: "#FFFFFF", fontWeight: 500 }}
height="19px"
fontWeight={500}
fontSize={"16px"}
lineHeight={"100%"}
sx={{ color: "#FFFFFF" }}
> >
Personal Information Personal Information
</Typography> </Typography>
@ -129,40 +116,22 @@ const ProfilePage = () => {
</Link> */} </Link> */}
</Stack> </Stack>
<Grid <Grid container spacing={3} sx={{ overflowX: "auto" }}>
container <Grid item xs={12} sm={4}>
width="1100px"
height="38px"
// gap={"100px"}
>
<Grid
item
xs={12}
sm={4}
width="64px"
height="16px"
fontSize={"14px"}
lineHeight={"100%"}
>
<Typography <Typography
variant="body1" variant="body2"
fontWeight={500} sx={{ color: "#FFFFFF", fontWeight: 500 }}
sx={{ color: "#FFFFFF" }}
> >
Full Name: Full Name:
</Typography> </Typography>
<Typography <Typography variant="body2" color="#D9D8D8">
variant="body2"
fontWeight={400}
color="#D9D8D8"
>
{user?.name || "N/A"} {user?.name || "N/A"}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} sm={4}> <Grid item xs={12} sm={4}>
<Typography <Typography
variant="body1" variant="body2"
sx={{ color: "#FFFFFF" }} sx={{ color: "#FFFFFF", fontWeight: 500 }}
> >
Phone: Phone:
</Typography> </Typography>
@ -172,8 +141,8 @@ const ProfilePage = () => {
</Grid> </Grid>
<Grid item xs={12} sm={4}> <Grid item xs={12} sm={4}>
<Typography <Typography
variant="body1" variant="body2"
sx={{ color: "#FFFFFF" }} sx={{ color: "#FFFFFF", fontWeight: 500 }}
> >
Email: Email:
</Typography> </Typography>
@ -181,24 +150,18 @@ const ProfilePage = () => {
{user?.email || "N/A"} {user?.email || "N/A"}
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12} sm={4}>
<Typography
variant="body2"
sx={{ color: "#FFFFFF", fontWeight: 500 }}
>
Bio:
</Typography>
<Typography variant="body2" color="#D9D8D8">
{user?.bio || "No bio available."}
</Typography>
</Grid>
</Grid> </Grid>
<Typography
variant="body1"
width="21px"
height="16px"
sx={{ color: "#FFFFFF" }}
>
Bio:
</Typography>
<Typography
variant="body2"
width="1100px"
height="32px"
color="#D9D8D8"
>
{user?.bio || "No bio available."}
</Typography>
</Stack> </Stack>
</CardContent> </CardContent>
</Card> </Card>

View file

@ -64,6 +64,7 @@ export const getCarPorts = createAsyncThunk<
const response = await http.get("/get-vehicle-port-dropdown"); const response = await http.get("/get-vehicle-port-dropdown");
return response.data.data; // Adjust based on actual API response return response.data.data; // Adjust based on actual API response
} catch (error: any) { } catch (error: any) {
return rejectWithValue( return rejectWithValue(
error?.response?.data?.message || "An error occurred" error?.response?.data?.message || "An error occurred"
@ -214,4 +215,4 @@ const bookSlice = createSlice({
}, },
}); });
export default bookSlice.reducer; export default bookSlice.reducer;

View file

@ -1,5 +1,5 @@
import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit"; import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios"; // import axios from "axios";
import http from "../../lib/https"; import http from "../../lib/https";
import { toast } from "sonner"; import { toast } from "sonner";
@ -384,4 +384,4 @@ const stationSlice = createSlice({
}, },
}); });
export default stationSlice.reducer; export default stationSlice.reducer;

View file

@ -1,5 +1,5 @@
import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit"; import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios"; // import axios from "axios";
import http from "../../lib/https"; import http from "../../lib/https";
import { toast } from "sonner"; import { toast } from "sonner";

View file

@ -23,7 +23,9 @@ const StationList = lazy(() => import("./pages/StationList"));
const EVSlotManagement = lazy(() => import("./pages/EVSlotManagement")); const EVSlotManagement = lazy(() => import("./pages/EVSlotManagement"));
const BookingList = lazy(() => import("./pages/BookingList")); const BookingList = lazy(() => import("./pages/BookingList"));
const EvSlotList = lazy(() => import("./pages/EvSlotList")); const EvSlotList = lazy(() => import("./pages/EvSlotList"));
const ExternalStationList = lazy(() => import("./pages/ExternalStationList/externalStationList.tsx")); const ExternalStationList = lazy(
() => import("./pages/ExternalStationList/externalStationList.tsx")
);
const AllManagersList = lazy(() => import("./pages/AllMangersList")); const AllManagersList = lazy(() => import("./pages/AllMangersList"));
const AvailableSlotsList = lazy(() => import("./pages/AvailableSlotsList")); const AvailableSlotsList = lazy(() => import("./pages/AvailableSlotsList"));
interface ProtectedRouteProps { interface ProtectedRouteProps {
@ -32,7 +34,7 @@ interface ProtectedRouteProps {
} }
// Protected Route Component // Protected Route Component
const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ component }) => { const ProtectedRoute: React.FC<ProtectedRouteProps> = ({ component }) => {
if (!localStorage.getItem("authToken")) { if (!localStorage.getItem("authToken")) {
return <Navigate to="/login" replace />; return <Navigate to="/login" replace />;
} }
@ -127,7 +129,9 @@ export default function AppRouter() {
<Route <Route
path="all-available-slots" path="all-available-slots"
element={ element={
<ProtectedRoute component={<AvailableSlotsList />} /> <ProtectedRoute
component={<AvailableSlotsList />}
/>
} }
/> />
</Route> </Route>

View file

@ -0,0 +1,27 @@
export const autofillFix = {
"& input:-webkit-autofill": {
WebkitBoxShadow: "0 0 0 1000px transparent inset !important",
WebkitTextFillColor: "white !important",
transition: "background-color 5000s ease-in-out 0s",
},
"& input:-webkit-autofill:hover": {
WebkitBoxShadow: "0 0 0 1000px transparent inset !important",
},
"& input:-webkit-autofill:focus": {
WebkitBoxShadow: "0 0 0 1000px transparent inset !important",
},
"& input:-webkit-autofill:active": {
WebkitBoxShadow: "0 0 0 1000px transparent inset !important",
},
"& input:-moz-autofill": {
boxShadow: "0 0 0 1000px transparent inset !important",
MozTextFillColor: "white !important",
transition: "background-color 5000s ease-in-out 0s",
},
"& input:autofill": {
boxShadow: "0 0 0 1000px transparent inset !important",
textFillColor: "white !important",
transition: "background-color 5000s ease-in-out 0s",
},
};

View file

@ -8,6 +8,7 @@ import CheckBoxOutlineBlankRoundedIcon from '@mui/icons-material/CheckBoxOutline
import CheckRoundedIcon from '@mui/icons-material/CheckRounded'; import CheckRoundedIcon from '@mui/icons-material/CheckRounded';
import RemoveRoundedIcon from '@mui/icons-material/RemoveRounded'; import RemoveRoundedIcon from '@mui/icons-material/RemoveRounded';
import { gray, brand } from '../themePrimitives'; import { gray, brand } from '../themePrimitives';
import {autofillFix} from './autoFill';
/* eslint-disable import/prefer-default-export */ /* eslint-disable import/prefer-default-export */
export const inputsCustomizations = { export const inputsCustomizations = {
@ -379,6 +380,7 @@ export const inputsCustomizations = {
styleOverrides: { styleOverrides: {
input: { input: {
padding: 0, padding: 0,
...autofillFix,
}, },
root: ({ theme }) => ({ root: ({ theme }) => ({
padding: '8px 12px', padding: '8px 12px',

View file

@ -8,6 +8,7 @@ import CheckBoxOutlineBlankRoundedIcon from "@mui/icons-material/CheckBoxOutline
import CheckRoundedIcon from "@mui/icons-material/CheckRounded"; import CheckRoundedIcon from "@mui/icons-material/CheckRounded";
import RemoveRoundedIcon from "@mui/icons-material/RemoveRounded"; import RemoveRoundedIcon from "@mui/icons-material/RemoveRounded";
import { gray, brand } from "../themePrimitives"; import { gray, brand } from "../themePrimitives";
import { autofillFix } from "./autoFill";
/* eslint-disable import/prefer-default-export */ /* eslint-disable import/prefer-default-export */
export const inputsCustomizations: Components<Theme> = { export const inputsCustomizations: Components<Theme> = {
@ -393,6 +394,7 @@ export const inputsCustomizations: Components<Theme> = {
styleOverrides: { styleOverrides: {
input: { input: {
padding: 0, padding: 0,
...autofillFix,
}, },
root: ({ theme }) => ({ root: ({ theme }) => ({
padding: "8px 12px", padding: "8px 12px",