dev-jaanvi #1

Open
jaanvi wants to merge 155 commits from dev-jaanvi into main
14 changed files with 784 additions and 437 deletions
Showing only changes of commit b2945a83f5 - Show all commits

View file

@ -8,7 +8,6 @@ import {
InputAdornment, InputAdornment,
Select, Select,
MenuItem, MenuItem,
InputLabel,
FormControl, FormControl,
} from "@mui/material"; } from "@mui/material";
import CloseIcon from "@mui/icons-material/Close"; import CloseIcon from "@mui/icons-material/Close";
@ -21,12 +20,7 @@ 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"; import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
export default function AddManagerModal({ export default function AddManagerModal({ open, handleClose }) {
open,
handleClose,
handleAddManager,
// Assume the stations prop contains a list of station objects with 'id' and 'name'
}) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { const {
control, control,
@ -34,7 +28,10 @@ export default function AddManagerModal({
handleSubmit, handleSubmit,
formState: { errors }, formState: { errors },
reset, reset,
} = useForm(); clearErrors,
} = useForm({
mode: "onChange", // Trigger validation on change for real-time feedback
});
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const stations = useSelector( const stations = useSelector(
(state: RootState) => state?.stationReducer.stations (state: RootState) => state?.stationReducer.stations
@ -46,7 +43,6 @@ export default function AddManagerModal({
// Handle form submission // Handle form submission
const onSubmit = async (data: any) => { const onSubmit = async (data: any) => {
// Retrieve the stationId based on the stationName selected
const selectedStation = stations.find( const selectedStation = stations.find(
(station) => station.name === data.stationName (station) => station.name === data.stationName
); );
@ -55,22 +51,29 @@ export default function AddManagerModal({
email: data.email, email: data.email,
phone: data.phone, phone: data.phone,
password: data.password, password: data.password,
stationId: selectedStation?.id, // Send stationId here stationId: selectedStation?.id,
}; };
try { try {
// Dispatch the addManager action
await dispatch(addManager(managerData)); await dispatch(addManager(managerData));
dispatch(managerList()); dispatch(managerList());
handleClose(); // Close modal after successful addition clearErrors(); // Clear errors on successful submission
reset(); // Reset form fields reset(); // Reset form fields on successful submission
handleClose(); // Close modal
} catch (error) { } catch (error) {
console.error("Error adding manager:", error); console.error("Error adding manager:", error);
} }
}; };
// Handle modal close, clearing errors and resetting form
const handleModalClose = () => {
clearErrors(); // Clear errors when closing via close icon
reset(); // Reset form fields when closing via close icon
handleClose(); // Close modal
};
const togglePasswordVisibility = (e: React.MouseEvent) => { const togglePasswordVisibility = (e: React.MouseEvent) => {
e.preventDefault(); // Prevent focus loss e.preventDefault();
setShowPassword((prev) => !prev); setShowPassword((prev) => !prev);
}; };
@ -79,9 +82,9 @@ export default function AddManagerModal({
open={open} open={open}
onClose={(e, reason) => { onClose={(e, reason) => {
if (reason === "backdropClick") { if (reason === "backdropClick") {
return; return; // Prevent closing on backdrop click
} }
handleClose(); // Close modal when clicking cross or cancel handleModalClose();
}} }}
aria-labelledby="add-manager-modal" aria-labelledby="add-manager-modal"
> >
@ -92,7 +95,7 @@ export default function AddManagerModal({
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
borderRadius: 2, borderRadius: 2,
@ -106,10 +109,15 @@ export default function AddManagerModal({
alignItems: "center", alignItems: "center",
}} }}
> >
<Typography variant="h6" fontWeight={600} fontSize={"16px"}> <Typography
variant="h6"
fontWeight={600}
fontSize={"16px"}
color="#D0E1E9"
>
Add Manager Add Manager
</Typography> </Typography>
<CustomIconButton onClick={handleClose}> <CustomIconButton onClick={handleModalClose}>
<CloseIcon /> <CloseIcon />
</CustomIconButton> </CustomIconButton>
</Box> </Box>
@ -122,7 +130,11 @@ export default function AddManagerModal({
{/* Manager Name */} {/* Manager Name */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1, ...autofillFix }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Manager Name Manager Name
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -159,7 +171,11 @@ 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}
color="#D0E1E9"
>
Select Station Select Station
</Typography> </Typography>
<FormControl <FormControl
@ -167,13 +183,21 @@ export default function AddManagerModal({
size="small" size="small"
error={!!errors.stationName} error={!!errors.stationName}
> >
<Select <Controller
{...register("stationName", { name="stationName"
control={control}
rules={{
required: "Station Name is required", required: "Station Name is required",
})} }}
render={({ field }) => (
<Select
{...field}
onChange={(e) =>
field.onChange(e.target.value)
} // Update form state
value={field.value || ""} // Ensure controlled value
sx={{ marginTop: 1 }} sx={{ marginTop: 1 }}
displayEmpty displayEmpty
defaultValue=""
renderValue={(selected) => { renderValue={(selected) => {
if (!selected) { if (!selected) {
return ( return (
@ -182,7 +206,6 @@ export default function AddManagerModal({
</Typography> </Typography>
); );
} }
return selected; return selected;
}} }}
MenuProps={{ MenuProps={{
@ -209,6 +232,8 @@ export default function AddManagerModal({
</MenuItem> </MenuItem>
)} )}
</Select> </Select>
)}
/>
{errors.stationName && ( {errors.stationName && (
<Typography <Typography
color="error" color="error"
@ -226,7 +251,11 @@ export default function AddManagerModal({
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
{/* Email */} {/* Email */}
<Box sx={{ flex: 1, ...autofillFix }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Email Email
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -243,7 +272,8 @@ export default function AddManagerModal({
required: "Email is required", required: "Email is required",
pattern: { pattern: {
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message: "Invalid email address", message:
"Please enter a valid email address (e.g., example@domain.com).",
}, },
})} })}
/> />
@ -251,7 +281,11 @@ export default function AddManagerModal({
{/* Password */} {/* Password */}
<Box sx={{ flex: 1, ...autofillFix }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Password Password
</Typography> </Typography>
<Controller <Controller
@ -319,7 +353,11 @@ 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, ...autofillFix }}> <Box sx={{ flex: 1, ...autofillFix }}>
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Phone Number Phone Number
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -343,7 +381,7 @@ export default function AddManagerModal({
if (value.length > 14) { if (value.length > 14) {
return "Phone number must be at most 14 digits"; return "Phone number must be at most 14 digits";
} }
return true; // No errors return true;
}, },
})} })}
/> />
@ -361,12 +399,12 @@ export default function AddManagerModal({
<Button <Button
type="submit" type="submit"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#000000",
borderRadius: "8px", borderRadius: "8px",
fontSize: "16px", fontSize: "16px",
width: "117px", width: "125px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#DFECF1" },
}} }}
> >
Add Manager Add Manager

View file

@ -35,6 +35,7 @@ export default function AddStationModal({
handleSubmit, handleSubmit,
formState: { errors }, formState: { errors },
reset, reset,
clearErrors,
} = useForm(); } = useForm();
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -83,7 +84,11 @@ export default function AddStationModal({
.filter((vehicle) => selectedVehicles.includes(vehicle.name)) .filter((vehicle) => selectedVehicles.includes(vehicle.name))
.map((vehicle) => vehicle.id); .map((vehicle) => vehicle.id);
}; };
const handleModalClose = () => {
clearErrors();
reset();
handleClose();
};
const onSubmit = (data: any) => { const onSubmit = (data: any) => {
const vehicleIds = getVehicleIds(); // Get the ids of the selected vehicles const vehicleIds = getVehicleIds(); // Get the ids of the selected vehicles
@ -95,7 +100,7 @@ export default function AddStationModal({
}; };
handleAddStation(payload); handleAddStation(payload);
handleClose(); // Close modal after adding handleClose();
reset(); reset();
setSelectedVehicles([]); setSelectedVehicles([]);
setSelectedBrands([]); // Reset selected brands after submission setSelectedBrands([]); // Reset selected brands after submission
@ -119,7 +124,7 @@ export default function AddStationModal({
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
borderRadius: 2, borderRadius: 2,
@ -133,10 +138,15 @@ export default function AddStationModal({
alignItems: "center", alignItems: "center",
}} }}
> >
<Typography variant="h6" fontWeight={600} fontSize={"16px"}> <Typography
variant="h6"
fontWeight={600}
fontSize={"16px"}
color="#D0E1E9"
>
Add Charging Station Add Charging Station
</Typography> </Typography>
<CustomIconButton onClick={handleClose}> <CustomIconButton onClick={handleModalClose}>
<CloseIcon /> <CloseIcon />
</CustomIconButton> </CustomIconButton>
</Box> </Box>
@ -163,7 +173,11 @@ export default function AddStationModal({
...autofillFix, ...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Station Name Station Name
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -199,7 +213,11 @@ export default function AddStationModal({
...autofillFix, ...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Station Location Station Location
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -215,7 +233,7 @@ export default function AddStationModal({
} }
{...register("registeredAddress", { {...register("registeredAddress", {
required: required:
"Registered Address is required", "Station Location is required",
})} })}
/> />
</Box> </Box>
@ -230,7 +248,11 @@ export default function AddStationModal({
width: "100%", width: "100%",
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Total Slots Total Slots
</Typography> </Typography>
<CustomTextField <CustomTextField
@ -270,6 +292,7 @@ export default function AddStationModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
sx={{ mb: 1 }} sx={{ mb: 1 }}
color="#D0E1E9"
> >
Vehicle Brand Vehicle Brand
</Typography> </Typography>
@ -283,7 +306,7 @@ export default function AddStationModal({
renderValue={(selected) => { renderValue={(selected) => {
if (selected.length === 0) { if (selected.length === 0) {
return ( return (
<Typography color="text.secondary"> <Typography color="#D0E1E9">
Choose Brands Choose Brands
</Typography> </Typography>
); );
@ -316,6 +339,7 @@ export default function AddStationModal({
<Typography <Typography
key={index} key={index}
variant="body2" variant="body2"
color="#454545"
> >
{brand {brand
? brand.name ? brand.name
@ -328,7 +352,7 @@ export default function AddStationModal({
{moreCount > 0 && ( {moreCount > 0 && (
<Typography <Typography
variant="body2" variant="body2"
color="textSecondary" color="#454545"
> >
+{moreCount} more +{moreCount} more
</Typography> </Typography>
@ -385,6 +409,7 @@ export default function AddStationModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
sx={{ mb: 1 }} sx={{ mb: 1 }}
color="#D0E1E9"
> >
Vehicle Name Vehicle Name
</Typography> </Typography>
@ -402,7 +427,7 @@ export default function AddStationModal({
renderValue={(selected) => { renderValue={(selected) => {
if (selected.length === 0) { if (selected.length === 0) {
return ( return (
<Typography color="text.secondary"> <Typography color="#454545">
{selectedBrands.length === {selectedBrands.length ===
0 0
? "Select brand first" ? "Select brand first"
@ -433,6 +458,7 @@ export default function AddStationModal({
<Typography <Typography
key={index} key={index}
variant="body2" variant="body2"
color="#454545"
> >
{name} {name}
</Typography> </Typography>
@ -441,7 +467,7 @@ export default function AddStationModal({
{moreCount > 0 && ( {moreCount > 0 && (
<Typography <Typography
variant="body2" variant="body2"
color="textSecondary" color="#454545"
> >
+{moreCount} more +{moreCount} more
</Typography> </Typography>
@ -501,12 +527,12 @@ export default function AddStationModal({
<Button <Button
type="submit" type="submit"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#000000",
borderRadius: "8px", borderRadius: "8px",
fontSize: "16px", fontSize: "16px",
width: "117px", width: "117px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#DFECF1" },
}} }}
> >
Add Station Add Station

View file

@ -9,6 +9,7 @@ export const CustomIconButton = styled(IconButton)({
backgroundColor: "transparent", backgroundColor: "transparent",
border: "none", border: "none",
}, },
color: "#D0E1E9",
}); });
// Custom TextField with different placeholder color // Custom TextField with different placeholder color

View file

@ -92,7 +92,7 @@ export default function AddVehicleModal({
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
borderRadius: 2, borderRadius: 2,
@ -106,7 +106,12 @@ export default function AddVehicleModal({
alignItems: "center", alignItems: "center",
}} }}
> >
<Typography variant="h6" fontWeight={600} fontSize={"16px"}> <Typography
variant="h6"
fontWeight={600}
fontSize={"16px"}
color="#D0E1E9"
>
Add Vehicle Add Vehicle
</Typography> </Typography>
<CustomIconButton onClick={handleClose}> <CustomIconButton onClick={handleClose}>
@ -133,6 +138,7 @@ export default function AddVehicleModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Vehicle Name Vehicle Name
</Typography> </Typography>
@ -183,6 +189,7 @@ export default function AddVehicleModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Company Company
</Typography> </Typography>
@ -226,6 +233,7 @@ export default function AddVehicleModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Model Name Model Name
</Typography> </Typography>
@ -259,6 +267,7 @@ export default function AddVehicleModal({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Charge Type Charge Type
</Typography> </Typography>
@ -290,17 +299,22 @@ export default function AddVehicleModal({
...autofillFix, ...autofillFix,
}} }}
> >
<Typography variant="body2" fontWeight={500} mb={0.5}> <Typography
variant="body2"
fontWeight={500}
mb={0.5}
color="#D0E1E9"
>
Upload Image Upload Image
</Typography> </Typography>
<Button <Button
component="label" component="label"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#000000",
borderRadius: "8px", borderRadius: "8px",
width: "100%", width: "100%",
"&:hover": { backgroundColor: "#52ACDF" }, "&:hover": { backgroundColor: "#DFECF1" },
}} }}
> >
Choose Image Choose Image
@ -346,12 +360,12 @@ export default function AddVehicleModal({
<Button <Button
type="submit" type="submit"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#00000",
borderRadius: "8px", borderRadius: "8px",
fontSize: "16px", fontSize: "16px",
width: "117px", width: "117px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#DFECF1" },
}} }}
> >
Add Vehicle Add Vehicle

View file

@ -6,86 +6,126 @@ import TableCell, { tableCellClasses } from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer"; import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead"; import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow"; import TableRow from "@mui/material/TableRow";
import Paper, { paperClasses } from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import { adminList, deleteAdmin } from "../../redux/slices/adminSlice.ts";
import { vehicleList, deleteVehicle } from "../../redux/slices/VehicleSlice.ts";
import { deleteManager, managerList } from "../../redux/slices/managerSlice.ts";
import { useDispatch, useSelector } from "react-redux";
import { import {
Box, Box,
Button, Button,
InputAdornment, InputAdornment,
Menu,
IconButton,
Pagination, Pagination,
TextField, TextField,
Typography, Typography,
IconButton,
Menu,
MenuItem,
} from "@mui/material"; } from "@mui/material";
import MoreVertIcon from "@mui/icons-material/MoreVert";
import VisibilityIcon from "@mui/icons-material/Visibility";
import EditIcon from "@mui/icons-material/Edit"; import EditIcon from "@mui/icons-material/Edit";
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
jaanvi marked this conversation as resolved Outdated

Color codes are already defined in the theme; use theme values instead of hardcoded colors.
Theme file path src/shared-theme/AppTheme.tsx

Color codes are already defined in the theme; use theme values instead of hardcoded colors. Theme file path src/shared-theme/AppTheme.tsx
import VisibilityIcon from "@mui/icons-material/Visibility"; import SearchIcon from "@mui/icons-material/Search";
jaanvi marked this conversation as resolved Outdated

Don't use the hardcoded color codes

Don't use the hardcoded color codes
import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded"; import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
import DeleteModal from "../Modals/DeleteModal/index.tsx"; import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "../../redux/store/store.ts"; import { AppDispatch, RootState } from "../../redux/store/store.ts";
import DeleteModal from "../Modals/DeleteModal/index.tsx";
import ViewModal from "../Modals/ViewModal/index.tsx"; import ViewModal from "../Modals/ViewModal/index.tsx";
import VehicleViewModal from "../Modals/VehicleViewModal/index.tsx"; import VehicleViewModal from "../Modals/VehicleViewModal/index.tsx";
import ManagerViewModal from "../Modals/ViewManagerModal/";
import SearchIcon from "@mui/icons-material/Search";
import TuneIcon from "@mui/icons-material/Tune";
import { CustomIconButton } from "../AddUserModal/styled.css";
import ManagerViewModal from "../Modals/ViewManagerModal/index.tsx";
import UserViewModal from "../Modals/UserViewModal/index.tsx"; import UserViewModal from "../Modals/UserViewModal/index.tsx";
import StationViewModal from "../Modals/StationViewModal/index.tsx";
import { adminList, deleteAdmin } from "../../redux/slices/adminSlice.ts";
import { vehicleList, deleteVehicle } from "../../redux/slices/VehicleSlice.ts";
import { deleteManager, managerList } from "../../redux/slices/managerSlice.ts";
import { deleteUser, userList } from "../../redux/slices/userSlice.ts"; import { deleteUser, userList } from "../../redux/slices/userSlice.ts";
import { deleteStation, stationList } from "../../redux/slices/stationSlice.ts"; import { deleteStation, stationList } from "../../redux/slices/stationSlice.ts";
import StationViewModal from "../Modals/StationViewModal/index.tsx";
import { import {
deleteSlot, deleteSlot,
fetchAvailableSlots, fetchAvailableSlots,
} from "../../redux/slices/slotSlice.ts"; } from "../../redux/slices/slotSlice.ts";
import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts"; import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts";
import AddCircleIcon from "@mui/icons-material/AddCircle"; import {
deleteStationDetails,
stationDetailList,
} from "../../redux/slices/managerStationSlice.ts";
import { CustomIconButton } from "../AddUserModal/styled.css.tsx";
import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx"; import { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward"; // Styled Components
import { deleteStationDetails, stationDetailList } from "../../redux/slices/managerStationSlice.ts";
import ManagerStationDetails from "../../pages/ManagerStationDetails/index.tsx";
// Styled components for customization
const StyledTableCell = styled(TableCell)(({ theme }) => ({ const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.body}`]: {
fontSize: "16px",
borderBottom: "1px solid rgba(87, 85, 85, 0.53)",
color: "#000000",
backgroundColor: "#D0E1E9",
},
[`&.${tableCellClasses.head}`]: { [`&.${tableCellClasses.head}`]: {
backgroundColor: "#000000", backgroundColor: "#000000",
color: "#D0E1E9", color: "#D0E1E9",
fontWeight: 600,
fontSize: "16px",
padding: "12px 16px",
borderBottom: "none", borderBottom: "none",
//borderRight: "1px solid rgba(141, 135, 135, 0.51)",
position: "sticky", position: "sticky",
top: 0, top: 0,
zIndex: 10, zIndex: 10,
transition: "background-color 0.2s ease",
"&:hover": {
backgroundColor: "#2A2A2A",
cursor: "pointer",
},
// Make the "Action" header cell sticky
"&.action-cell": {
right: 0,
zIndex: 11, // Higher z-index to ensure it stays above other headers
boxShadow: "-4px 0 8px rgba(0, 0, 0, 0.1)",
},
},
[`&.${tableCellClasses.body}`]: {
fontSize: "16px",
padding: "12px 16px",
borderBottom: "1px solid rgba(255, 255, 255, 0.1)",
color: "#333333",
transition: "background-color 0.2s ease",
// Make the "Action" body cell sticky
"&.action-cell": {
position: "sticky",
right: 0,
zIndex: 2,
boxShadow: "-4px 0 8px rgba(0, 0, 0, 0.1)",
backgroundColor: "#DFECF1", // Match row background
"&:hover": {
backgroundColor: "#D0E1E9", // Match row hover background
},
},
}, },
})); }));
const StyledTableRow = styled(TableRow)(({ theme }) => ({ const StyledTableRow = styled(TableRow)(({ theme }) => ({
backgroundColor: "#DFECF1",
transition: "background-color 0.2s ease",
"&:hover": {
backgroundColor: "#D0E1E9", backgroundColor: "#D0E1E9",
"& td, th": { },
"& td, & th": {
borderColor: "#454545", borderColor: "#454545",
borderWidth: "1px", borderWidth: "1px",
borderBottom: "1px solid #454545", borderBottom: "1px solid #454545",
color: "#000000",
backgroundColor: "#D0E1E9",
}, },
})); }));
const StyledTableContainer = styled(TableContainer)(({ theme }) => ({
borderRadius: "12px",
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.1)",
"&::-webkit-scrollbar": {
height: "6px",
},
"&::-webkit-scrollbar-track": {
background: "#D0E1E9",
},
"&::-webkit-scrollbar-thumb": {
background: "#000000",
borderRadius: "3px",
},
}));
// Interfaces
export interface Column { export interface Column {
id: string; id: string;
label: string; label: string;
align?: "left" | "center" | "right"; align?: "left" | "center" | "right";
} }
interface Row { interface Row {
@ -102,11 +142,16 @@ interface CustomTableProps {
setViewModal: Function; setViewModal: Function;
deleteModal: boolean; deleteModal: boolean;
handleStatusToggle?: (id: string, currentStatus: number | boolean) => void; handleStatusToggle?: (id: string, currentStatus: number | boolean) => void;
tableType: string; // Adding tableType prop to change header text dynamically tableType: string;
handleClickOpen?: () => void; handleClickOpen?: () => void;
statusField?: string; // Optional field to indicate the status column statusField?: string;
statusValue?: boolean; // Optional normalized status value statusValue?: boolean;
}
// Sorting State Interface
interface SortConfig {
key: string;
direction: "asc" | "desc" | null;
} }
const CustomTable: React.FC<CustomTableProps> = ({ const CustomTable: React.FC<CustomTableProps> = ({
@ -123,18 +168,19 @@ const CustomTable: React.FC<CustomTableProps> = ({
handleClickOpen, handleClickOpen,
}) => { }) => {
const dispatch = useDispatch<AppDispatch>(); const dispatch = useDispatch<AppDispatch>();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = React.useState<Row | null>(null); const [selectedRow, setSelectedRow] = React.useState<Row | null>(null);
const [searchQuery, setSearchQuery] = React.useState(""); const [searchQuery, setSearchQuery] = React.useState("");
const [currentPage, setCurrentPage] = React.useState(1); const [currentPage, setCurrentPage] = React.useState(1);
const [sortConfig, setSortConfig] = React.useState<SortConfig>({
key: "",
direction: null,
});
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [menuRow, setMenuRow] = React.useState<Row | null>(null);
const usersPerPage = 10; const usersPerPage = 10;
const { user } = useSelector((state: RootState) => state?.profileReducer); const { user } = useSelector((state: RootState) => state?.profileReducer);
const open = Boolean(anchorEl);
const [sortOrder, setSortOrder] = React.useState<"asc" | "desc" | null>(
null
);
// ... [imports remain the same, no changes needed] ...
// Helper Functions
const getTitleByType = (type: string) => { const getTitleByType = (type: string) => {
const titles: { [key: string]: string } = { const titles: { [key: string]: string } = {
admin: "Admins", admin: "Admins",
@ -143,9 +189,9 @@ const CustomTable: React.FC<CustomTableProps> = ({
manager: "Managers", manager: "Managers",
"all-managers": "Managers", "all-managers": "Managers",
vehicle: "Vehicles", vehicle: "Vehicles",
station: "Charging Station", station: "Charging Stations",
"external-station": "Charging Station", "external-station": "Charging Stations",
booking: "Booking", booking: "Bookings",
slots: "Slots", slots: "Slots",
"all-available-slots": "Available Slots", "all-available-slots": "Available Slots",
"manager-station": "Station Details", "manager-station": "Station Details",
@ -196,23 +242,76 @@ const CustomTable: React.FC<CustomTableProps> = ({
return true; return true;
}; };
const handleClick = (event: React.MouseEvent<HTMLElement>, row: Row) => {
setAnchorEl(event.currentTarget);
setSelectedRow(row);
setRowData(row);
};
const handleClose = () => {
setAnchorEl(null);
};
const isImage = (value: any) => { const isImage = (value: any) => {
if (typeof value === "string") { if (typeof value === "string") {
return value.startsWith("http") || value.startsWith("data:image"); // Check for URL or base64 image return value.startsWith("http") || value.startsWith("data:image");
} }
return false; return false;
}; };
// Sorting Logic
const handleSort = (key: string) => {
setSortConfig((prev) => {
if (prev.key === key) {
if (prev.direction === "asc") return { key, direction: "desc" };
if (prev.direction === "desc") return { key, direction: null };
return { key, direction: "asc" };
}
return { key, direction: "asc" };
});
};
const sortedRows = React.useMemo(() => {
if (!sortConfig.key || !sortConfig.direction) return [...rows];
return [...rows].sort((a, b) => {
const aValue = a[sortConfig.key];
const bValue = b[sortConfig.key];
if (aValue == null && bValue == null) return 0;
if (aValue == null) return sortConfig.direction === "asc" ? 1 : -1;
if (bValue == null) return sortConfig.direction === "asc" ? -1 : 1;
if (typeof aValue === "number" && typeof bValue === "number") {
return sortConfig.direction === "asc"
? aValue - bValue
: bValue - aValue;
}
const aStr = String(aValue).toLowerCase();
const bStr = String(bValue).toLowerCase();
return sortConfig.direction === "asc"
? aStr.localeCompare(bStr)
: bStr.localeCompare(aStr);
});
}, [rows, sortConfig]);
// Filtering Logic
const filteredRows = sortedRows.filter((row) => {
if (!searchQuery.trim()) return true;
const lowerCaseQuery = searchQuery.toLowerCase().trim();
return (
(row.name && row.name.toLowerCase().includes(lowerCaseQuery)) ||
(row.registeredAddress &&
row.registeredAddress.toLowerCase().includes(lowerCaseQuery)) ||
(row.stationName &&
row.stationName.toLowerCase().includes(lowerCaseQuery))
);
});
// Pagination Logic
const indexOfLastRow = currentPage * usersPerPage;
const indexOfFirstRow = indexOfLastRow - usersPerPage;
const currentRows = filteredRows.slice(indexOfFirstRow, indexOfLastRow);
const handlePageChange = (
_event: React.ChangeEvent<unknown>,
value: number
) => {
setCurrentPage(value);
};
// Action Handlers
const handleDeleteButton = (id: string | undefined) => { const handleDeleteButton = (id: string | undefined) => {
if (!id) { if (!id) {
console.error("ID not found", id); console.error("ID not found", id);
@ -221,36 +320,34 @@ const CustomTable: React.FC<CustomTableProps> = ({
switch (tableType) { switch (tableType) {
case "admin": case "admin":
dispatch(deleteAdmin(id || "")); dispatch(deleteAdmin(id));
break; break;
case "vehicle": case "vehicle":
dispatch(deleteVehicle(id || "")); dispatch(deleteVehicle(id));
break; break;
case "manager": case "manager":
dispatch(deleteManager(id || "")); dispatch(deleteManager(id));
break; break;
case "user": case "user":
dispatch(deleteUser(id || "")); dispatch(deleteUser(id));
break; break;
case "station": case "station":
dispatch(deleteStation(id || "")); dispatch(deleteStation(id));
break; break;
case "slots": case "slots":
dispatch(deleteSlot(id || "")); dispatch(deleteSlot(id));
break; break;
case "booking": case "booking":
dispatch(deleteBooking(id || "")); dispatch(deleteBooking(id));
break; break;
case "manager-station": case "manager-station":
dispatch(deleteStationDetails(id || "")); dispatch(deleteStationDetails(id));
break; break;
default: default:
console.error("Unknown table type:", tableType); console.error("Unknown table type:", tableType);
return; return;
} }
setDeleteModal(false); // Close the modal only after deletion setDeleteModal(false);
handleClose();
}; };
const handleViewButton = (id: string | undefined) => { const handleViewButton = (id: string | undefined) => {
@ -284,62 +381,55 @@ const CustomTable: React.FC<CustomTableProps> = ({
console.error("Unknown table type:", tableType); console.error("Unknown table type:", tableType);
return; return;
} }
setViewModal(false); setViewModal(false);
}; };
const handleToggleStatus = () => {
if (selectedRow) {
handleStatusToggle?.(selectedRow.id, !selectedRow.statusValue); // Toggle the boolean statusValue
}
handleClose();
};
const handleSort = () => {
setSortOrder((prevSortOrder) =>
prevSortOrder === "asc" ? "desc" : "asc"
);
};
const handleEditButton = (row: Row) => { const handleEditButton = (row: Row) => {
setModalOpen(true); setModalOpen(true);
setRowData(row); setRowData(row);
}; };
const sortedRows = React.useMemo(() => { // Menu Handlers
let sorted = [...rows]; const handleMenuOpen = (event: React.MouseEvent<HTMLElement>, row: Row) => {
if (sortOrder) { setAnchorEl(event.currentTarget);
sorted.sort((a, b) => { setMenuRow(row);
if (a.name < b.name) return sortOrder === "asc" ? -1 : 1; };
if (a.name > b.name) return sortOrder === "asc" ? 1 : -1;
return 0; const handleMenuClose = () => {
}); setAnchorEl(null);
setMenuRow(null);
};
const handleMenuAction = (action: string) => {
if (!menuRow) return;
switch (action) {
case "view":
setSelectedRow(menuRow);
setViewModal(true);
break;
case "edit":
handleEditButton(menuRow);
break;
case "delete":
setDeleteModal(true);
setSelectedRow(menuRow);
break;
default:
break;
} }
return sorted; handleMenuClose();
}, [rows, sortOrder]);
const filteredRows = sortedRows.filter((row) => {
if (!searchQuery.trim()) return true;
const lowerCaseQuery = searchQuery.toLowerCase().trim();
return (
(row.name && row.name.toLowerCase().includes(lowerCaseQuery)) ||
(row.registeredAddress &&
row.registeredAddress.toLowerCase().includes(lowerCaseQuery)) ||
(row.stationName &&
row.stationName.toLowerCase().includes(lowerCaseQuery))
);
});
const indexOfLastRow = currentPage * usersPerPage;
const indexOfFirstRow = indexOfLastRow - usersPerPage;
const currentRows = filteredRows.slice(indexOfFirstRow, indexOfLastRow);
const handlePageChange = (
_event: React.ChangeEvent<unknown>,
value: number
) => {
setCurrentPage(value);
}; };
return ( return (
<Box sx={{ width: "100%", padding: "24px", borderRadius: "12px" }}> <Box
sx={{
width: "100%",
padding: "24px",
backgroundColor: "#D0E1E9",
borderRadius: "12px",
}}
>
{/* Header Section */}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -353,48 +443,47 @@ const handleToggleStatus = () => {
> >
<Typography <Typography
sx={{ sx={{
color: "#000000",
fontWeight: 600, fontWeight: 600,
fontSize: "30px", fontSize: "30px",
letterSpacing: "-0.5px",
}} }}
> >
{getTitleByType(tableType)} {getTitleByType(tableType)}
</Typography> </Typography>
{/* Right Side: Search + Add */}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
gap: 2, gap: 2,
flexWrap: "wrap", flexWrap: "wrap",
justifyContent: "flex-end",
}} }}
> >
<TextField <TextField
variant="outlined" variant="outlined"
placeholder="Search" placeholder="Search"
sx={{ sx={{
width: { xs: "100%", sm: "300px", md: "300px" }, width: { xs: "100%", sm: "300px" },
input: { color: "#454545" }, ...autofillFix,
"& .MuiOutlinedInput-root": { "& .MuiOutlinedInput-root": {
borderRadius: "12px", borderRadius: "8px",
height: "44px", height: "40px",
"& fieldset": { borderColor: "#454545" }, backgroundColor: "#FFFFFF",
"&:hover fieldset": { borderColor: "#454545" }, "& fieldset": { borderColor: "#D1D5DB" },
"&:hover fieldset": { borderColor: "#9CA3AF" },
"&.Mui-focused fieldset": { "&.Mui-focused fieldset": {
borderColor: "#52ACDF", borderColor: "#3B82F6",
}, },
}, },
"& .MuiInputBase-input::placeholder": { "& .MuiInputBase-input": {
color: "#454545", fontSize: "14px",
opacity: 1, color: "#1A1A1A",
}, },
}} }}
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
<SearchIcon sx={{ color: "#454545" }} /> <SearchIcon sx={{ color: "#6B7280" }} />
</InputAdornment> </InputAdornment>
), ),
}} }}
@ -402,16 +491,21 @@ const handleToggleStatus = () => {
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
/> />
{/* Conditionally show Add Button */}
{shouldShowAddButton(user?.userType, tableType) && ( {shouldShowAddButton(user?.userType, tableType) && (
<Button <Button
sx={{ sx={{
backgroundColor: "#000000", backgroundColor: "#000000",
color: "white", color: "#FFFFFF",
minWidth: "115px", fontWeight: 600,
fontSize: "16px", fontSize: "14px",
paddingX: 2, padding: "8px 16px",
"&:hover": { backgroundColor: "#000000" }, borderRadius: "8px",
textTransform: "none",
"&:hover": {
backgroundColor: "#454545",
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
},
transition: "all 0.2s ease",
}} }}
onClick={handleClickOpen} onClick={handleClickOpen}
> >
@ -422,33 +516,58 @@ const handleToggleStatus = () => {
</Box> </Box>
{/* Table Section */} {/* Table Section */}
<TableContainer <StyledTableContainer>
component={Paper}
sx={{
marginTop: "24px",
borderRadius: "12px",
overflow: "auto",
maxWidth: "100%",
"&::-webkit-scrollbar": {
height: "3px",
},
"&::-webkit-scrollbar-track": {
background: "#1C1C1C",
},
"&::-webkit-scrollbar-thumb": {
background: "#52ACDF",
borderRadius: "4px",
},
}}
>
<Table sx={{ minWidth: "750px", tableLayout: "auto" }}> <Table sx={{ minWidth: "750px", tableLayout: "auto" }}>
<TableHead> <TableHead>
{" "}
<TableRow> <TableRow>
{columns.map((column) => ( {columns.map((column) => (
<StyledTableCell key={column.id}> <StyledTableCell
key={column.id}
align={column.align}
onClick={
column.id !== "action"
? () => handleSort(column.id)
: undefined
}
sx={{
cursor:
column.id !== "action"
? "pointer"
: "default",
}}
className={
column.id === "action"
? "action-cell"
: undefined
} // Add action-cell class
>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: 1,
}}
>
{column.label} {column.label}
{column.id !== "action" &&
sortConfig.key === column.id &&
sortConfig.direction &&
(sortConfig.direction === "asc" ? (
<ArrowUpwardIcon
sx={{
fontSize: "16px",
color: "#FFFFFF",
}}
/>
) : (
<ArrowDownwardIcon
sx={{
fontSize: "16px",
color: "#FFFFFF",
}}
/>
))}
</Box>
</StyledTableCell> </StyledTableCell>
))} ))}
</TableRow> </TableRow>
@ -458,88 +577,156 @@ const handleToggleStatus = () => {
<StyledTableRow> <StyledTableRow>
<StyledTableCell <StyledTableCell
colSpan={columns.length} colSpan={columns.length}
sx={{ textAlign: "center", py: 4 }}
>
<Typography
sx={{ sx={{
textAlign: "center", color: "#6B7280",
padding: "32px 0", fontSize: "16px",
}} }}
> >
{getEmptyMessage(tableType)} {getEmptyMessage(tableType)}
</Typography>
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
) : ( ) : (
currentRows.map((row, rowIndex) => ( currentRows.map((row, rowIndex) => (
<StyledTableRow key={rowIndex}> <StyledTableRow key={rowIndex}>
{columns.map((column) => ( {columns.map((column) => (
// In CustomTable.tsx, update the status column rendering logic inside the TableBody
<StyledTableCell <StyledTableCell
key={column.id} key={column.id}
sx={{ align={column.align}
color: "#000000", className={
backgroundColor: "#D0E1E9", column.id === "action"
...(column.id === "action" && { ? "action-cell"
position: "sticky", : undefined
right: 0, } // Add action-cell class
zIndex: 2,
boxShadow:
"-5px 0 5px -2px rgba(0,0,0,0.15)",
}),
}}
> >
{column.id === "action" ? ( {column.id === "action" ? (
<> <Box>
<CustomIconButton <CustomIconButton
onClick={() => { onClick={(e) =>
setSelectedRow(row); handleMenuOpen(
setViewModal(true); e,
row
)
}
sx={{
color: "#6B7280",
"&:hover": {
color: "#454545",
},
transition:
"color 0.2s ease",
}}
>
<MoreVertIcon />
</CustomIconButton>
<Menu
anchorEl={anchorEl}
open={
Boolean(anchorEl) &&
menuRow === row
}
onClose={
handleMenuClose
}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
PaperProps={{
sx: {
borderRadius:
"8px",
boxShadow:
"0 2px 8px rgba(0, 0, 0, 0.15)",
},
}}
>
<MenuItem
onClick={() =>
handleMenuAction(
"view"
)
}
sx={{
color: "#000000",
fontSize:
"16px",
display: "flex",
alignItems:
"center",
gap: 1,
}} }}
> >
<VisibilityIcon <VisibilityIcon
sx={{ sx={{
fontSize:
"18px",
color: "#454545", color: "#454545",
"&:hover": {
color: "#6B7280",
},
}} }}
/> />
</CustomIconButton> View
</MenuItem>
<CustomIconButton <MenuItem
onClick={() => onClick={() =>
handleEditButton( handleMenuAction(
row "edit"
) )
} }
sx={{
color: "#000000",
fontSize:
"16px",
display: "flex",
alignItems:
"center",
gap: 1,
}}
> >
<EditIcon <EditIcon
sx={{ sx={{
fontSize:
"18px",
color: "#454545", color: "#454545",
"&:hover": {
color: "#6B7280",
},
}} }}
/> />
</CustomIconButton> Edit
</MenuItem>
<CustomIconButton <MenuItem
onClick={() => { onClick={() =>
setDeleteModal( handleMenuAction(
true "delete"
); )
setSelectedRow(row); }
sx={{
color: "#000000",
fontSize:
"14px",
display: "flex",
alignItems:
"center",
gap: 1,
}} }}
> >
<DeleteIcon <DeleteIcon
sx={{ sx={{
fontSize:
"18px",
color: "#454545", color: "#454545",
"&:hover": {
color: "#6B7280",
},
}} }}
/> />
</CustomIconButton> Delete
</> </MenuItem>
</Menu>
</Box>
) : row.statusField && ) : row.statusField &&
column.id === row.statusField ? ( // Check if statusField matches the column column.id === row.statusField ? (
<Button <Button
variant="outlined" variant="outlined"
onClick={(e) => { onClick={(e) => {
@ -548,26 +735,25 @@ const handleToggleStatus = () => {
handleStatusToggle?.( handleStatusToggle?.(
row.id, row.id,
!row.statusValue !row.statusValue
); // Toggle the opposite of current statusValue );
}} }}
color="primary"
sx={{ sx={{
justifyContent: fontSize: "12px",
"flex-start", fontWeight: 600,
py: 0.5, borderRadius: "6px",
px: 1.5, color: row.statusValue
fontSize: "0.75rem", ? "#10B981"
fontWeight: "600", : "#EF4444",
borderRadius: "4px",
color: "#000000",
border: "1px solid #000000",
backgroundColor:
"transparent",
"&:hover": {
borderColor: borderColor:
"#000000", row.statusValue
? "#10B981"
: "#EF4444",
padding: "4px 12px",
"&:hover": {
backgroundColor: backgroundColor:
"transparent", row.statusValue
? "rgba(16, 185, 129, 0.1)"
: "rgba(239, 68, 68, 0.1)",
}, },
"&::before": { "&::before": {
content: '""', content: '""',
@ -580,7 +766,7 @@ const handleToggleStatus = () => {
backgroundColor: backgroundColor:
row.statusValue row.statusValue
? "#10B981" ? "#10B981"
: "#EF4444", // Green for true, red for false : "#EF4444",
}, },
}} }}
> >
@ -593,8 +779,8 @@ const handleToggleStatus = () => {
src={row[column.id]} src={row[column.id]}
alt="Row" alt="Row"
style={{ style={{
width: "50px", width: "40px",
height: "50px", height: "40px",
borderRadius: "50%", borderRadius: "50%",
objectFit: "cover", objectFit: "cover",
}} }}
@ -609,7 +795,8 @@ const handleToggleStatus = () => {
)} )}
</TableBody> </TableBody>
</Table> </Table>
</TableContainer> </StyledTableContainer>
{/* Pagination */} {/* Pagination */}
<Box sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}> <Box sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}>
<Pagination <Pagination
@ -618,16 +805,21 @@ const handleToggleStatus = () => {
onChange={handlePageChange} onChange={handlePageChange}
sx={{ sx={{
"& .MuiPaginationItem-root": { "& .MuiPaginationItem-root": {
color: "#000000", color: "#1A1A1A",
fontSize: "16px",
}, },
"& .Mui-selected": { "& .Mui-selected": {
backgroundColor: "#000000", backgroundColor: "#000000",
color: "#FFFFFF", color: "#FFFFFF",
"&:hover": {
backgroundColor: "#000000",
},
}, },
}} }}
/> />
</Box> </Box>
{/* Modals */}
{viewModal && tableType === "admin" && ( {viewModal && tableType === "admin" && (
<ViewModal <ViewModal
handleView={() => handleViewButton(selectedRow?.id)} handleView={() => handleViewButton(selectedRow?.id)}
@ -644,7 +836,6 @@ const handleToggleStatus = () => {
id={selectedRow?.id} id={selectedRow?.id}
/> />
)} )}
{viewModal && tableType === "vehicle" && ( {viewModal && tableType === "vehicle" && (
<VehicleViewModal <VehicleViewModal
handleView={() => handleViewButton(selectedRow?.id)} handleView={() => handleViewButton(selectedRow?.id)}
@ -669,26 +860,6 @@ const handleToggleStatus = () => {
id={selectedRow?.id} id={selectedRow?.id}
/> />
)} )}
{tableType === "role" && (
<Button
variant="text"
onClick={(e) => {
e.stopPropagation();
handleToggleStatus();
}}
color="secondary"
sx={{
justifyContent: "flex-start",
py: 0,
fontWeight: "bold",
}}
>
{selectedRow?.statusValue === 1 ? "Deactivate" : "Activate"}
</Button>
)}
{/* Modals */}
{deleteModal && ( {deleteModal && (
<DeleteModal <DeleteModal
handleDelete={() => handleDeleteButton(selectedRow?.id)} handleDelete={() => handleDeleteButton(selectedRow?.id)}

View file

@ -114,7 +114,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
borderRadius: 2, borderRadius: 2,
@ -128,7 +128,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
alignItems: "center", alignItems: "center",
}} }}
> >
<Typography variant="h6" fontWeight={600}> <Typography variant="h6" fontWeight={600} color="#D0E1E9">
Edit Manager Edit Manager
</Typography> </Typography>
<CustomIconButton onClick={handleClose}> <CustomIconButton onClick={handleClose}>
@ -143,7 +143,12 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}> <Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}>
{/* Manager Name */} {/* Manager Name */}
<Box sx={{ flex: "1 1 48%" }}> <Box sx={{ flex: "1 1 48%" }}>
<Typography variant="body2" fontWeight={500} mb={0.5}> <Typography
variant="body2"
fontWeight={500}
mb={0.5}
color="#D0E1E9"
>
Manager Name Manager Name
</Typography> </Typography>
<Controller <Controller
@ -172,7 +177,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
placeholder="Enter Manager Name" placeholder="Enter Manager Name"
size="small" size="small"
sx={{ marginTop: 1 }} sx={{ marginTop: 1 }}
error={!!errors.name} error={!!errors.name}
helperText={errors.name?.message} helperText={errors.name?.message}
/> />
@ -182,13 +186,25 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
{/* Email */} {/* Email */}
<Box sx={{ flex: "1 1 48%" }}> <Box sx={{ flex: "1 1 48%" }}>
<Typography variant="body2" fontWeight={500} mb={0.5}> <Typography
variant="body2"
fontWeight={500}
mb={0.5}
color="#D0E1E9"
>
Email Email
</Typography> </Typography>
<Controller <Controller
name="email" name="email"
control={control} control={control}
rules={{ required: "Email is required" }} rules={{
required: "Email is required",
pattern: {
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message:
"Please enter a valid email address (e.g., example@domain.com).",
},
}}
render={({ field }) => ( render={({ field }) => (
<CustomTextField <CustomTextField
{...field} {...field}
@ -196,7 +212,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
placeholder="Enter Email" placeholder="Enter Email"
size="small" size="small"
sx={{ marginTop: 1 }} sx={{ marginTop: 1 }}
error={!!errors.email} error={!!errors.email}
helperText={errors.email?.message} helperText={errors.email?.message}
/> />
@ -206,7 +221,12 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
{/* Phone Number */} {/* Phone Number */}
<Box sx={{ flex: "1 1 48%" }}> <Box sx={{ flex: "1 1 48%" }}>
<Typography variant="body2" fontWeight={500} mb={0.5}> <Typography
variant="body2"
fontWeight={500}
mb={0.5}
color="#D0E1E9"
>
Phone Number Phone Number
</Typography> </Typography>
<Controller <Controller
@ -234,7 +254,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
placeholder="Enter Phone Number" placeholder="Enter Phone Number"
size="small" size="small"
sx={{ marginTop: 1 }} sx={{ marginTop: 1 }}
error={!!errors.phone} error={!!errors.phone}
helperText={errors.phone?.message} helperText={errors.phone?.message}
/> />
@ -250,11 +269,11 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
<Button <Button
type="submit" type="submit"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#000000",
borderRadius: "8px", borderRadius: "8px",
width: "117px", width: "125px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#DFECF1" },
whiteSpace: "pre", whiteSpace: "pre",
}} }}
disabled={loading} disabled={loading}

View file

@ -55,6 +55,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
setValue, setValue,
reset, reset,
formState: { errors }, formState: { errors },
register,
} = useForm<FormData>({ } = useForm<FormData>({
defaultValues: { defaultValues: {
name: "", name: "",
@ -197,7 +198,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
borderRadius: 2, borderRadius: 2,
@ -211,7 +212,12 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
alignItems: "center", alignItems: "center",
}} }}
> >
<Typography variant="h6" fontWeight={600} fontSize={"16px"}> <Typography
variant="h6"
fontWeight={600}
fontSize={"16px"}
color="#D0E1E9"
>
Edit Charging Station Edit Charging Station
</Typography> </Typography>
<CustomIconButton onClick={handleClose}> <CustomIconButton onClick={handleClose}>
@ -237,6 +243,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Station Name Station Name
</Typography> </Typography>
@ -256,6 +263,20 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
? errors.name.message ? errors.name.message
: "" : ""
} }
{...register("name", {
required:
"Station Name is required",
minLength: {
value: 3,
message:
"Minimum 3 characters required",
},
maxLength: {
value: 30,
message:
"Maximum 30 characters allowed",
},
})}
/> />
)} )}
/> />
@ -271,6 +292,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Station Location Station Location
</Typography> </Typography>
@ -291,6 +313,10 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
.message .message
: "" : ""
} }
{...register("registeredAddress", {
required:
"Station Location is required",
})}
/> />
)} )}
/> />
@ -310,6 +336,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
variant="body2" variant="body2"
fontWeight={500} fontWeight={500}
mb={0.5} mb={0.5}
color="#D0E1E9"
> >
Total Slots Total Slots
</Typography> </Typography>
@ -330,6 +357,15 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
? errors.totalSlots.message ? errors.totalSlots.message
: "" : ""
} }
{...register("totalSlots", {
required:
"Total Slots are required",
min: {
value: 1,
message:
"At least 1 slot is required",
},
})}
/> />
)} )}
/> />
@ -345,7 +381,11 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
width: "100%", width: "100%",
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Select Vehicle Brands Select Vehicle Brands
</Typography> </Typography>
<FormControl fullWidth> <FormControl fullWidth>
@ -385,6 +425,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
<Typography <Typography
key={index} key={index}
variant="body2" variant="body2"
color="#454545"
> >
{brand {brand
? brand.name ? brand.name
@ -396,7 +437,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
{moreCount > 0 && ( {moreCount > 0 && (
<Typography <Typography
variant="body2" variant="body2"
color="textSecondary" color="#454545"
> >
+{moreCount} more +{moreCount} more
</Typography> </Typography>
@ -438,7 +479,11 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
width: "100%", width: "100%",
}} }}
> >
<Typography variant="body2" fontWeight={500}> <Typography
variant="body2"
fontWeight={500}
color="#D0E1E9"
>
Vehicle Name Vehicle Name
</Typography> </Typography>
<FormControl fullWidth> <FormControl fullWidth>
@ -471,6 +516,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
<Typography <Typography
key={index} key={index}
variant="body2" variant="body2"
color="#454545"
> >
{name} {name}
</Typography> </Typography>
@ -479,7 +525,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
{moreCount > 0 && ( {moreCount > 0 && (
<Typography <Typography
variant="body2" variant="body2"
color="textSecondary" color="#454545"
> >
+{moreCount} more +{moreCount} more
</Typography> </Typography>
@ -528,12 +574,12 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
<Button <Button
type="submit" type="submit"
sx={{ sx={{
backgroundColor: "#52ACDF", backgroundColor: "#D0E1E9",
color: "white", color: "#000000",
borderRadius: "8px", borderRadius: "8px",
fontSize: "16px", fontSize: "16px",
width: "117px", width: "150px",
"&:hover": { backgroundColor: "#439BC1" }, "&:hover": { backgroundColor: "#DFECF1" },
}} }}
> >
Update Station Update Station

View file

@ -15,14 +15,27 @@ const style = {
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 330, width: 330,
bgcolor: "#272727", bgcolor: "#000000",
color: "#D0E1E9",
borderRadius: 1.5, borderRadius: 1.5,
boxShadow: 24, boxShadow: 24,
p: 3, p: 3,
}; };
const btnStyle = { py: 1, px: 5, width: "50%", textTransform: "capitalize" }; const btnStyle = {
py: 1,
px: 5,
width: "50%",
textTransform: "capitalize",
backgroundColor: "#D0E1E9",
color: "#000000",
};
const btnStyleCancel = {
py: 1,
px: 5,
width: "50%",
textTransform: "capitalize",
};
export default function DeleteModal({ export default function DeleteModal({
open, open,
setDeleteModal, setDeleteModal,
@ -54,6 +67,7 @@ export default function DeleteModal({
alignItems: "center", alignItems: "center",
justifyContent: "flex-end", justifyContent: "flex-end",
marginTop: -3.5, marginTop: -3.5,
}} }}
> >
<CustomIconButton <CustomIconButton
@ -89,10 +103,10 @@ export default function DeleteModal({
Cancel Cancel
</Button> </Button>
<Button <Button
variant="contained"
type="button" type="button"
color="primary" variant="contained"
sx={btnStyle} color="error"
sx={btnStyleCancel}
onClick={() => handleDelete(id || "")} onClick={() => handleDelete(id || "")}
> >
Delete Delete

View file

@ -18,7 +18,7 @@ const style = {
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
borderRadius: 2, borderRadius: 2,
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)", boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
p: 4, p: 4,
@ -62,7 +62,10 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
width: "100%", width: "100%",
}} }}
> >
<Box sx={{ flex: 1, textAlign: "center" }}> <Box
sx={{ flex: 1, textAlign: "center" }}
color="#D0E1E9"
>
{selectedStation?.name || "Station"}'s Details {selectedStation?.name || "Station"}'s Details
</Box> </Box>
<CustomIconButton <CustomIconButton
@ -79,33 +82,33 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
{selectedStation ? ( {selectedStation ? (
<Grid container spacing={2} sx={{ width: "80%" }}> <Grid container spacing={2} sx={{ width: "80%" }}>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Station Name:</strong>{" "} <strong>Station Name:</strong>{" "}
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedStation.name} {selectedStation.name}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Station Location:</strong>{" "} <strong>Station Location:</strong>{" "}
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedStation.registeredAddress} {selectedStation.registeredAddress}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Total Slots:</strong> <strong>Total Slots:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedStation.totalSlots} {selectedStation.totalSlots}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Status:</strong> <strong>Status:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedStation.status === 1 {selectedStation.status === 1
? "Available" ? "Available"
: "Not Available"} : "Not Available"}
@ -115,7 +118,7 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
{/* Display Vehicles */} {/* Display Vehicles */}
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Vehicles:</strong> <strong>Vehicles:</strong>
</Typography> </Typography>
<Box <Box
@ -125,6 +128,7 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
gap: 1, gap: 1,
marginTop: 1, marginTop: 1,
}} }}
color="#D0E1E9"
> >
{selectedStation.allowedCars && {selectedStation.allowedCars &&
selectedStation.allowedCars.length > 0 ? ( selectedStation.allowedCars.length > 0 ? (
@ -138,15 +142,13 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
fontWeight: 500, fontWeight: 500,
}} }}
> >
{car.name}{","} {car.name}
{","}
</Typography> </Typography>
) )
) )
) : ( ) : (
<Typography <Typography variant="body2" color="#D0E1E9">
variant="body2"
color="text.secondary"
>
No vehicles available No vehicles available
</Typography> </Typography>
)} )}

View file

@ -17,7 +17,7 @@ const style = {
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
borderRadius: 2, borderRadius: 2,
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)", boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
p: 4, p: 4,
@ -61,7 +61,13 @@ export default function VehicleViewModal({ open, setViewModal, id }: Props) {
width: "100%", width: "100%",
}} }}
> >
<Box sx={{ flex: 1, textAlign: "center" }}> <Box
sx={{
flex: 1,
textAlign: "center",
color: "#D0E1E9",
}}
>
{selectedVehicle?.name || "Vehicle"}'s Details {selectedVehicle?.name || "Vehicle"}'s Details
</Box> </Box>
<Box <Box
@ -82,39 +88,43 @@ export default function VehicleViewModal({ open, setViewModal, id }: Props) {
{selectedVehicle ? ( {selectedVehicle ? (
<Grid container spacing={2} sx={{ width: "80%" }}> <Grid container spacing={2} sx={{ width: "80%" }}>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Name:</strong>{" "} <strong>Name:</strong>{" "}
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedVehicle.name} {selectedVehicle.name}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Company:</strong>{" "} <strong>Company:</strong>{" "}
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedVehicle.company} {selectedVehicle.company}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Model Name:</strong> <strong>Model Name:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedVehicle.modelName} {selectedVehicle.modelName}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Charge Type:</strong> <strong>Charge Type:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedVehicle.chargeType} {selectedVehicle.chargeType}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>
<Typography variant="body1" gutterBottom> <Typography
variant="body1"
gutterBottom
color="#D0E1E9"
>
<strong>Image:</strong> <strong>Image:</strong>
</Typography> </Typography>
{selectedVehicle.imageUrl ? ( {selectedVehicle.imageUrl ? (
@ -139,7 +149,7 @@ export default function VehicleViewModal({ open, setViewModal, id }: Props) {
}} }}
/> />
) : ( ) : (
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
No image available No image available
</Typography> </Typography>
)} )}

View file

@ -17,7 +17,7 @@ const style = {
left: "50%", left: "50%",
transform: "translate(-50%, -50%)", transform: "translate(-50%, -50%)",
width: 400, width: 400,
bgcolor: "background.paper", bgcolor: "#000000",
borderRadius: 2, borderRadius: 2,
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)", boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
p: 4, p: 4,
@ -35,7 +35,6 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
useEffect(() => { useEffect(() => {
if (id) { if (id) {
const manager = managers.find((manager) => manager.id === id); const manager = managers.find((manager) => manager.id === id);
setSelectedManager(manager || null); setSelectedManager(manager || null);
} }
@ -62,7 +61,13 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
width: "100%", width: "100%",
}} }}
> >
<Box sx={{ flex: 1, textAlign: "center" }}> <Box
sx={{
flex: 1,
textAlign: "center",
color: "#D0E1E9",
}}
>
{selectedManager?.name || "Manager"}'s Details {selectedManager?.name || "Manager"}'s Details
</Box> </Box>
<Box <Box
@ -71,6 +76,7 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
color: "#D0E1E9",
}} }}
> >
<CloseIcon /> <CloseIcon />
@ -83,42 +89,42 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
{selectedManager ? ( {selectedManager ? (
<Grid container spacing={2} sx={{ width: "80%" }}> <Grid container spacing={2} sx={{ width: "80%" }}>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Name:</strong> <strong>Name:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedManager.name} {selectedManager.name}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Email:</strong> <strong>Email:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedManager.email} {selectedManager.email}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Phone:</strong> <strong>Phone:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedManager.phone} {selectedManager.phone}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Station Location:</strong> <strong>Station Location:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedManager.chargingStation {selectedManager.chargingStation
?.registeredAddress || "Not Available"} ?.registeredAddress || "Not Available"}
</Typography> </Typography>
</Typography> </Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="body1"> <Typography variant="body1" color="#D0E1E9">
<strong>Station Name:</strong> <strong>Station Name:</strong>
<Typography variant="body2"> <Typography variant="body2" color="#D0E1E9">
{selectedManager.chargingStation?.name || {selectedManager.chargingStation?.name ||
"Not Available"} "Not Available"}
</Typography> </Typography>

View file

@ -1,4 +1,3 @@
import * as React from "react"; import * as React from "react";
import { ThemeProvider, Theme, createTheme } from "@mui/material/styles"; import { ThemeProvider, Theme, createTheme } from "@mui/material/styles";
import type { ThemeOptions } from "@mui/material/styles"; import type { ThemeOptions } from "@mui/material/styles";
@ -28,7 +27,7 @@ export default function AppTheme(props: AppThemeProps) {
paper: "#D0E1E9", // Dark cards paper: "#D0E1E9", // Dark cards
}, },
text: { text: {
primary: "#000000", // Already matches the image primary: "#454545", // Already matches the image
secondary: "#272727", // Already matches the image secondary: "#272727", // Already matches the image
}, },
success: { success: {
@ -55,6 +54,7 @@ export default function AppTheme(props: AppThemeProps) {
body2: { body2: {
fontSize: "0.875rem", fontSize: "0.875rem",
color: "#b0b0b0", color: "#b0b0b0",
fontWeight: 300,
}, },
}, },
cssVariables: { cssVariables: {

View file

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

View file

@ -385,7 +385,7 @@ export const inputsCustomizations: Components<Theme> = {
input: { input: {
"&::placeholder": { "&::placeholder": {
opacity: 0.7, opacity: 0.7,
color: gray[500], color: gray[600],
}, },
}, },
}, },