Table UI changes and manager , charging station modals ui chnaged
This commit is contained in:
parent
f353befab5
commit
b2945a83f5
|
@ -8,7 +8,6 @@ import {
|
|||
InputAdornment,
|
||||
Select,
|
||||
MenuItem,
|
||||
InputLabel,
|
||||
FormControl,
|
||||
} from "@mui/material";
|
||||
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 { autofillFix } from "../../shared-theme/customizations/autoFill.tsx";
|
||||
|
||||
export default function AddManagerModal({
|
||||
open,
|
||||
handleClose,
|
||||
handleAddManager,
|
||||
// Assume the stations prop contains a list of station objects with 'id' and 'name'
|
||||
}) {
|
||||
export default function AddManagerModal({ open, handleClose }) {
|
||||
const dispatch = useDispatch();
|
||||
const {
|
||||
control,
|
||||
|
@ -34,7 +28,10 @@ export default function AddManagerModal({
|
|||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
} = useForm();
|
||||
clearErrors,
|
||||
} = useForm({
|
||||
mode: "onChange", // Trigger validation on change for real-time feedback
|
||||
});
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const stations = useSelector(
|
||||
(state: RootState) => state?.stationReducer.stations
|
||||
|
@ -46,7 +43,6 @@ export default function AddManagerModal({
|
|||
|
||||
// Handle form submission
|
||||
const onSubmit = async (data: any) => {
|
||||
// Retrieve the stationId based on the stationName selected
|
||||
const selectedStation = stations.find(
|
||||
(station) => station.name === data.stationName
|
||||
);
|
||||
|
@ -55,22 +51,29 @@ export default function AddManagerModal({
|
|||
email: data.email,
|
||||
phone: data.phone,
|
||||
password: data.password,
|
||||
stationId: selectedStation?.id, // Send stationId here
|
||||
stationId: selectedStation?.id,
|
||||
};
|
||||
|
||||
try {
|
||||
// Dispatch the addManager action
|
||||
await dispatch(addManager(managerData));
|
||||
dispatch(managerList());
|
||||
handleClose(); // Close modal after successful addition
|
||||
reset(); // Reset form fields
|
||||
clearErrors(); // Clear errors on successful submission
|
||||
reset(); // Reset form fields on successful submission
|
||||
handleClose(); // Close modal
|
||||
} catch (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) => {
|
||||
e.preventDefault(); // Prevent focus loss
|
||||
e.preventDefault();
|
||||
setShowPassword((prev) => !prev);
|
||||
};
|
||||
|
||||
|
@ -79,9 +82,9 @@ export default function AddManagerModal({
|
|||
open={open}
|
||||
onClose={(e, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
return;
|
||||
return; // Prevent closing on backdrop click
|
||||
}
|
||||
handleClose(); // Close modal when clicking cross or cancel
|
||||
handleModalClose();
|
||||
}}
|
||||
aria-labelledby="add-manager-modal"
|
||||
>
|
||||
|
@ -92,7 +95,7 @@ export default function AddManagerModal({
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
|
@ -106,10 +109,15 @@ export default function AddManagerModal({
|
|||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
fontSize={"16px"}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Add Manager
|
||||
</Typography>
|
||||
<CustomIconButton onClick={handleClose}>
|
||||
<CustomIconButton onClick={handleModalClose}>
|
||||
<CloseIcon />
|
||||
</CustomIconButton>
|
||||
</Box>
|
||||
|
@ -122,7 +130,11 @@ export default function AddManagerModal({
|
|||
{/* Manager Name */}
|
||||
<Box sx={{ display: "flex", gap: 2, mb: 2 }}>
|
||||
<Box sx={{ flex: 1, ...autofillFix }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Manager Name
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -159,7 +171,11 @@ export default function AddManagerModal({
|
|||
{/* Station Dropdown */}
|
||||
<Box sx={{ display: "flex", gap: 2, mb: 2 }}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Select Station
|
||||
</Typography>
|
||||
<FormControl
|
||||
|
@ -167,48 +183,57 @@ export default function AddManagerModal({
|
|||
size="small"
|
||||
error={!!errors.stationName}
|
||||
>
|
||||
<Select
|
||||
{...register("stationName", {
|
||||
<Controller
|
||||
name="stationName"
|
||||
control={control}
|
||||
rules={{
|
||||
required: "Station Name is required",
|
||||
})}
|
||||
sx={{ marginTop: 1 }}
|
||||
displayEmpty
|
||||
defaultValue=""
|
||||
renderValue={(selected) => {
|
||||
if (!selected) {
|
||||
return (
|
||||
<Typography color="text.secondary">
|
||||
Choose Station
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
return selected;
|
||||
}}
|
||||
MenuProps={{
|
||||
PaperProps: {
|
||||
style: {
|
||||
maxHeight: 224,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{Array.isArray(stations) &&
|
||||
stations.length > 0 ? (
|
||||
stations.map((station) => (
|
||||
<MenuItem
|
||||
key={station.id}
|
||||
value={station.name}
|
||||
>
|
||||
{station.name}
|
||||
</MenuItem>
|
||||
))
|
||||
) : (
|
||||
<MenuItem disabled>
|
||||
No stations available
|
||||
</MenuItem>
|
||||
render={({ field }) => (
|
||||
<Select
|
||||
{...field}
|
||||
onChange={(e) =>
|
||||
field.onChange(e.target.value)
|
||||
} // Update form state
|
||||
value={field.value || ""} // Ensure controlled value
|
||||
sx={{ marginTop: 1 }}
|
||||
displayEmpty
|
||||
renderValue={(selected) => {
|
||||
if (!selected) {
|
||||
return (
|
||||
<Typography color="text.secondary">
|
||||
Choose Station
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
return selected;
|
||||
}}
|
||||
MenuProps={{
|
||||
PaperProps: {
|
||||
style: {
|
||||
maxHeight: 224,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{Array.isArray(stations) &&
|
||||
stations.length > 0 ? (
|
||||
stations.map((station) => (
|
||||
<MenuItem
|
||||
key={station.id}
|
||||
value={station.name}
|
||||
>
|
||||
{station.name}
|
||||
</MenuItem>
|
||||
))
|
||||
) : (
|
||||
<MenuItem disabled>
|
||||
No stations available
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
)}
|
||||
</Select>
|
||||
/>
|
||||
{errors.stationName && (
|
||||
<Typography
|
||||
color="error"
|
||||
|
@ -226,7 +251,11 @@ export default function AddManagerModal({
|
|||
<Box sx={{ display: "flex", gap: 2, mb: 2 }}>
|
||||
{/* Email */}
|
||||
<Box sx={{ flex: 1, ...autofillFix }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Email
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -243,7 +272,8 @@ export default function AddManagerModal({
|
|||
required: "Email is required",
|
||||
pattern: {
|
||||
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 */}
|
||||
<Box sx={{ flex: 1, ...autofillFix }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Password
|
||||
</Typography>
|
||||
<Controller
|
||||
|
@ -319,7 +353,11 @@ export default function AddManagerModal({
|
|||
{/* Phone Number */}
|
||||
<Box sx={{ display: "flex", gap: 2, mb: 2 }}>
|
||||
<Box sx={{ flex: 1, ...autofillFix }}>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Phone Number
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -343,7 +381,7 @@ export default function AddManagerModal({
|
|||
if (value.length > 14) {
|
||||
return "Phone number must be at most 14 digits";
|
||||
}
|
||||
return true; // No errors
|
||||
return true;
|
||||
},
|
||||
})}
|
||||
/>
|
||||
|
@ -361,12 +399,12 @@ export default function AddManagerModal({
|
|||
<Button
|
||||
type="submit"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#000000",
|
||||
borderRadius: "8px",
|
||||
fontSize: "16px",
|
||||
width: "117px",
|
||||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
width: "125px",
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
}}
|
||||
>
|
||||
Add Manager
|
||||
|
|
|
@ -35,6 +35,7 @@ export default function AddStationModal({
|
|||
handleSubmit,
|
||||
formState: { errors },
|
||||
reset,
|
||||
clearErrors,
|
||||
} = useForm();
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
@ -83,7 +84,11 @@ export default function AddStationModal({
|
|||
.filter((vehicle) => selectedVehicles.includes(vehicle.name))
|
||||
.map((vehicle) => vehicle.id);
|
||||
};
|
||||
|
||||
const handleModalClose = () => {
|
||||
clearErrors();
|
||||
reset();
|
||||
handleClose();
|
||||
};
|
||||
const onSubmit = (data: any) => {
|
||||
const vehicleIds = getVehicleIds(); // Get the ids of the selected vehicles
|
||||
|
||||
|
@ -95,7 +100,7 @@ export default function AddStationModal({
|
|||
};
|
||||
|
||||
handleAddStation(payload);
|
||||
handleClose(); // Close modal after adding
|
||||
handleClose();
|
||||
reset();
|
||||
setSelectedVehicles([]);
|
||||
setSelectedBrands([]); // Reset selected brands after submission
|
||||
|
@ -119,7 +124,7 @@ export default function AddStationModal({
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
|
@ -133,10 +138,15 @@ export default function AddStationModal({
|
|||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
fontSize={"16px"}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Add Charging Station
|
||||
</Typography>
|
||||
<CustomIconButton onClick={handleClose}>
|
||||
<CustomIconButton onClick={handleModalClose}>
|
||||
<CloseIcon />
|
||||
</CustomIconButton>
|
||||
</Box>
|
||||
|
@ -163,7 +173,11 @@ export default function AddStationModal({
|
|||
...autofillFix,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Station Name
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -199,7 +213,11 @@ export default function AddStationModal({
|
|||
...autofillFix,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Station Location
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -215,7 +233,7 @@ export default function AddStationModal({
|
|||
}
|
||||
{...register("registeredAddress", {
|
||||
required:
|
||||
"Registered Address is required",
|
||||
"Station Location is required",
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
|
@ -230,7 +248,11 @@ export default function AddStationModal({
|
|||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Total Slots
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
|
@ -270,6 +292,7 @@ export default function AddStationModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
sx={{ mb: 1 }}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Vehicle Brand
|
||||
</Typography>
|
||||
|
@ -283,7 +306,7 @@ export default function AddStationModal({
|
|||
renderValue={(selected) => {
|
||||
if (selected.length === 0) {
|
||||
return (
|
||||
<Typography color="text.secondary">
|
||||
<Typography color="#D0E1E9">
|
||||
Choose Brands
|
||||
</Typography>
|
||||
);
|
||||
|
@ -316,6 +339,7 @@ export default function AddStationModal({
|
|||
<Typography
|
||||
key={index}
|
||||
variant="body2"
|
||||
color="#454545"
|
||||
>
|
||||
{brand
|
||||
? brand.name
|
||||
|
@ -328,7 +352,7 @@ export default function AddStationModal({
|
|||
{moreCount > 0 && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
color="#454545"
|
||||
>
|
||||
+{moreCount} more
|
||||
</Typography>
|
||||
|
@ -385,6 +409,7 @@ export default function AddStationModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
sx={{ mb: 1 }}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Vehicle Name
|
||||
</Typography>
|
||||
|
@ -402,7 +427,7 @@ export default function AddStationModal({
|
|||
renderValue={(selected) => {
|
||||
if (selected.length === 0) {
|
||||
return (
|
||||
<Typography color="text.secondary">
|
||||
<Typography color="#454545">
|
||||
{selectedBrands.length ===
|
||||
0
|
||||
? "Select brand first"
|
||||
|
@ -433,6 +458,7 @@ export default function AddStationModal({
|
|||
<Typography
|
||||
key={index}
|
||||
variant="body2"
|
||||
color="#454545"
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
|
@ -441,7 +467,7 @@ export default function AddStationModal({
|
|||
{moreCount > 0 && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
color="#454545"
|
||||
>
|
||||
+{moreCount} more
|
||||
</Typography>
|
||||
|
@ -501,12 +527,12 @@ export default function AddStationModal({
|
|||
<Button
|
||||
type="submit"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#000000",
|
||||
borderRadius: "8px",
|
||||
fontSize: "16px",
|
||||
width: "117px",
|
||||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
}}
|
||||
>
|
||||
Add Station
|
||||
|
|
|
@ -9,6 +9,7 @@ export const CustomIconButton = styled(IconButton)({
|
|||
backgroundColor: "transparent",
|
||||
border: "none",
|
||||
},
|
||||
color: "#D0E1E9",
|
||||
});
|
||||
|
||||
// Custom TextField with different placeholder color
|
||||
|
|
|
@ -92,7 +92,7 @@ export default function AddVehicleModal({
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
|
@ -106,7 +106,12 @@ export default function AddVehicleModal({
|
|||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
fontSize={"16px"}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Add Vehicle
|
||||
</Typography>
|
||||
<CustomIconButton onClick={handleClose}>
|
||||
|
@ -133,6 +138,7 @@ export default function AddVehicleModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Vehicle Name
|
||||
</Typography>
|
||||
|
@ -183,6 +189,7 @@ export default function AddVehicleModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Company
|
||||
</Typography>
|
||||
|
@ -226,6 +233,7 @@ export default function AddVehicleModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Model Name
|
||||
</Typography>
|
||||
|
@ -259,6 +267,7 @@ export default function AddVehicleModal({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Charge Type
|
||||
</Typography>
|
||||
|
@ -290,17 +299,22 @@ export default function AddVehicleModal({
|
|||
...autofillFix,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Upload Image
|
||||
</Typography>
|
||||
<Button
|
||||
component="label"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#000000",
|
||||
borderRadius: "8px",
|
||||
width: "100%",
|
||||
"&:hover": { backgroundColor: "#52ACDF" },
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
}}
|
||||
>
|
||||
Choose Image
|
||||
|
@ -346,12 +360,12 @@ export default function AddVehicleModal({
|
|||
<Button
|
||||
type="submit"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#00000",
|
||||
borderRadius: "8px",
|
||||
fontSize:"16px",
|
||||
fontSize: "16px",
|
||||
width: "117px",
|
||||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
}}
|
||||
>
|
||||
Add Vehicle
|
||||
|
|
|
@ -6,86 +6,126 @@ import TableCell, { tableCellClasses } from "@mui/material/TableCell";
|
|||
import TableContainer from "@mui/material/TableContainer";
|
||||
import TableHead from "@mui/material/TableHead";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import Paper, { paperClasses } 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 Paper from "@mui/material/Paper";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
InputAdornment,
|
||||
Menu,
|
||||
IconButton,
|
||||
Pagination,
|
||||
TextField,
|
||||
Typography,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuItem,
|
||||
} 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 DeleteIcon from "@mui/icons-material/Delete";
|
||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||
import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded";
|
||||
import DeleteModal from "../Modals/DeleteModal/index.tsx";
|
||||
import SearchIcon from "@mui/icons-material/Search";
|
||||
import ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
|
||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppDispatch, RootState } from "../../redux/store/store.ts";
|
||||
import DeleteModal from "../Modals/DeleteModal/index.tsx";
|
||||
import ViewModal from "../Modals/ViewModal/index.tsx";
|
||||
import VehicleViewModal from "../Modals/VehicleViewModal/index.tsx";
|
||||
|
||||
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 ManagerViewModal from "../Modals/ViewManagerModal/";
|
||||
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 { deleteStation, stationList } from "../../redux/slices/stationSlice.ts";
|
||||
import StationViewModal from "../Modals/StationViewModal/index.tsx";
|
||||
import {
|
||||
deleteSlot,
|
||||
fetchAvailableSlots,
|
||||
} from "../../redux/slices/slotSlice.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 ArrowUpwardIcon from "@mui/icons-material/ArrowUpward";
|
||||
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
|
||||
import { deleteStationDetails, stationDetailList } from "../../redux/slices/managerStationSlice.ts";
|
||||
import ManagerStationDetails from "../../pages/ManagerStationDetails/index.tsx";
|
||||
// Styled components for customization
|
||||
|
||||
// Styled Components
|
||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||
[`&.${tableCellClasses.body}`]: {
|
||||
fontSize: "16px",
|
||||
borderBottom: "1px solid rgba(87, 85, 85, 0.53)",
|
||||
color: "#000000",
|
||||
backgroundColor: "#D0E1E9",
|
||||
},
|
||||
[`&.${tableCellClasses.head}`]: {
|
||||
backgroundColor: "#000000",
|
||||
color: "#D0E1E9",
|
||||
fontWeight: 600,
|
||||
fontSize: "16px",
|
||||
padding: "12px 16px",
|
||||
borderBottom: "none",
|
||||
//borderRight: "1px solid rgba(141, 135, 135, 0.51)",
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
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 }) => ({
|
||||
backgroundColor: "#D0E1E9",
|
||||
"& td, th": {
|
||||
backgroundColor: "#DFECF1",
|
||||
transition: "background-color 0.2s ease",
|
||||
"&:hover": {
|
||||
backgroundColor: "#D0E1E9",
|
||||
},
|
||||
"& td, & th": {
|
||||
borderColor: "#454545",
|
||||
borderWidth: "1px",
|
||||
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 {
|
||||
id: string;
|
||||
label: string;
|
||||
align?: "left" | "center" | "right";
|
||||
|
||||
}
|
||||
|
||||
interface Row {
|
||||
|
@ -102,11 +142,16 @@ interface CustomTableProps {
|
|||
setViewModal: Function;
|
||||
deleteModal: boolean;
|
||||
handleStatusToggle?: (id: string, currentStatus: number | boolean) => void;
|
||||
tableType: string; // Adding tableType prop to change header text dynamically
|
||||
tableType: string;
|
||||
handleClickOpen?: () => void;
|
||||
statusField?: string; // Optional field to indicate the status column
|
||||
statusValue?: boolean; // Optional normalized status value
|
||||
|
||||
statusField?: string;
|
||||
statusValue?: boolean;
|
||||
}
|
||||
|
||||
// Sorting State Interface
|
||||
interface SortConfig {
|
||||
key: string;
|
||||
direction: "asc" | "desc" | null;
|
||||
}
|
||||
|
||||
const CustomTable: React.FC<CustomTableProps> = ({
|
||||
|
@ -123,18 +168,19 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
|||
handleClickOpen,
|
||||
}) => {
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
const [selectedRow, setSelectedRow] = React.useState<Row | null>(null);
|
||||
const [searchQuery, setSearchQuery] = React.useState("");
|
||||
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 { 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 titles: { [key: string]: string } = {
|
||||
admin: "Admins",
|
||||
|
@ -143,9 +189,9 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
|||
manager: "Managers",
|
||||
"all-managers": "Managers",
|
||||
vehicle: "Vehicles",
|
||||
station: "Charging Station",
|
||||
"external-station": "Charging Station",
|
||||
booking: "Booking",
|
||||
station: "Charging Stations",
|
||||
"external-station": "Charging Stations",
|
||||
booking: "Bookings",
|
||||
slots: "Slots",
|
||||
"all-available-slots": "Available Slots",
|
||||
"manager-station": "Station Details",
|
||||
|
@ -196,23 +242,76 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
|||
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) => {
|
||||
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;
|
||||
};
|
||||
|
||||
// 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) => {
|
||||
if (!id) {
|
||||
console.error("ID not found", id);
|
||||
|
@ -221,36 +320,34 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
|||
|
||||
switch (tableType) {
|
||||
case "admin":
|
||||
dispatch(deleteAdmin(id || ""));
|
||||
dispatch(deleteAdmin(id));
|
||||
break;
|
||||
case "vehicle":
|
||||
dispatch(deleteVehicle(id || ""));
|
||||
dispatch(deleteVehicle(id));
|
||||
break;
|
||||
case "manager":
|
||||
dispatch(deleteManager(id || ""));
|
||||
dispatch(deleteManager(id));
|
||||
break;
|
||||
case "user":
|
||||
dispatch(deleteUser(id || ""));
|
||||
dispatch(deleteUser(id));
|
||||
break;
|
||||
case "station":
|
||||
dispatch(deleteStation(id || ""));
|
||||
dispatch(deleteStation(id));
|
||||
break;
|
||||
case "slots":
|
||||
dispatch(deleteSlot(id || ""));
|
||||
dispatch(deleteSlot(id));
|
||||
break;
|
||||
case "booking":
|
||||
dispatch(deleteBooking(id || ""));
|
||||
dispatch(deleteBooking(id));
|
||||
break;
|
||||
case "manager-station":
|
||||
dispatch(deleteStationDetails(id || ""));
|
||||
dispatch(deleteStationDetails(id));
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error("Unknown table type:", tableType);
|
||||
return;
|
||||
}
|
||||
setDeleteModal(false); // Close the modal only after deletion
|
||||
handleClose();
|
||||
setDeleteModal(false);
|
||||
};
|
||||
|
||||
const handleViewButton = (id: string | undefined) => {
|
||||
|
@ -284,62 +381,55 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
|||
console.error("Unknown table type:", tableType);
|
||||
return;
|
||||
}
|
||||
|
||||
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) => {
|
||||
setModalOpen(true);
|
||||
setRowData(row);
|
||||
};
|
||||
|
||||
const sortedRows = React.useMemo(() => {
|
||||
let sorted = [...rows];
|
||||
if (sortOrder) {
|
||||
sorted.sort((a, b) => {
|
||||
if (a.name < b.name) return sortOrder === "asc" ? -1 : 1;
|
||||
if (a.name > b.name) return sortOrder === "asc" ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
// Menu Handlers
|
||||
const handleMenuOpen = (event: React.MouseEvent<HTMLElement>, row: Row) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
setMenuRow(row);
|
||||
};
|
||||
|
||||
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;
|
||||
}, [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);
|
||||
handleMenuClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ width: "100%", padding: "24px", borderRadius: "12px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
padding: "24px",
|
||||
backgroundColor: "#D0E1E9",
|
||||
borderRadius: "12px",
|
||||
}}
|
||||
>
|
||||
{/* Header Section */}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
@ -353,48 +443,47 @@ const handleToggleStatus = () => {
|
|||
>
|
||||
<Typography
|
||||
sx={{
|
||||
color: "#000000",
|
||||
fontWeight: 600,
|
||||
fontSize: "30px",
|
||||
letterSpacing: "-0.5px",
|
||||
}}
|
||||
>
|
||||
{getTitleByType(tableType)}
|
||||
</Typography>
|
||||
|
||||
{/* Right Side: Search + Add */}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 2,
|
||||
flexWrap: "wrap",
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<TextField
|
||||
variant="outlined"
|
||||
placeholder="Search"
|
||||
sx={{
|
||||
width: { xs: "100%", sm: "300px", md: "300px" },
|
||||
input: { color: "#454545" },
|
||||
width: { xs: "100%", sm: "300px" },
|
||||
...autofillFix,
|
||||
"& .MuiOutlinedInput-root": {
|
||||
borderRadius: "12px",
|
||||
height: "44px",
|
||||
"& fieldset": { borderColor: "#454545" },
|
||||
"&:hover fieldset": { borderColor: "#454545" },
|
||||
borderRadius: "8px",
|
||||
height: "40px",
|
||||
backgroundColor: "#FFFFFF",
|
||||
"& fieldset": { borderColor: "#D1D5DB" },
|
||||
"&:hover fieldset": { borderColor: "#9CA3AF" },
|
||||
"&.Mui-focused fieldset": {
|
||||
borderColor: "#52ACDF",
|
||||
borderColor: "#3B82F6",
|
||||
},
|
||||
},
|
||||
"& .MuiInputBase-input::placeholder": {
|
||||
color: "#454545",
|
||||
opacity: 1,
|
||||
"& .MuiInputBase-input": {
|
||||
fontSize: "14px",
|
||||
color: "#1A1A1A",
|
||||
},
|
||||
}}
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchIcon sx={{ color: "#454545" }} />
|
||||
<SearchIcon sx={{ color: "#6B7280" }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
|
@ -402,16 +491,21 @@ const handleToggleStatus = () => {
|
|||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
|
||||
{/* Conditionally show Add Button */}
|
||||
{shouldShowAddButton(user?.userType, tableType) && (
|
||||
<Button
|
||||
sx={{
|
||||
backgroundColor: "#000000",
|
||||
color: "white",
|
||||
minWidth: "115px",
|
||||
fontSize: "16px",
|
||||
paddingX: 2,
|
||||
"&:hover": { backgroundColor: "#000000" },
|
||||
color: "#FFFFFF",
|
||||
fontWeight: 600,
|
||||
fontSize: "14px",
|
||||
padding: "8px 16px",
|
||||
borderRadius: "8px",
|
||||
textTransform: "none",
|
||||
"&:hover": {
|
||||
backgroundColor: "#454545",
|
||||
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
||||
},
|
||||
transition: "all 0.2s ease",
|
||||
}}
|
||||
onClick={handleClickOpen}
|
||||
>
|
||||
|
@ -422,33 +516,58 @@ const handleToggleStatus = () => {
|
|||
</Box>
|
||||
|
||||
{/* Table Section */}
|
||||
<TableContainer
|
||||
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",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<StyledTableContainer>
|
||||
<Table sx={{ minWidth: "750px", tableLayout: "auto" }}>
|
||||
<TableHead>
|
||||
{" "}
|
||||
<TableRow>
|
||||
{columns.map((column) => (
|
||||
<StyledTableCell key={column.id}>
|
||||
{column.label}
|
||||
<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.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>
|
||||
))}
|
||||
</TableRow>
|
||||
|
@ -458,88 +577,156 @@ const handleToggleStatus = () => {
|
|||
<StyledTableRow>
|
||||
<StyledTableCell
|
||||
colSpan={columns.length}
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
padding: "32px 0",
|
||||
}}
|
||||
sx={{ textAlign: "center", py: 4 }}
|
||||
>
|
||||
{getEmptyMessage(tableType)}
|
||||
<Typography
|
||||
sx={{
|
||||
color: "#6B7280",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
{getEmptyMessage(tableType)}
|
||||
</Typography>
|
||||
</StyledTableCell>
|
||||
</StyledTableRow>
|
||||
) : (
|
||||
currentRows.map((row, rowIndex) => (
|
||||
<StyledTableRow key={rowIndex}>
|
||||
{columns.map((column) => (
|
||||
// In CustomTable.tsx, update the status column rendering logic inside the TableBody
|
||||
<StyledTableCell
|
||||
key={column.id}
|
||||
sx={{
|
||||
color: "#000000",
|
||||
backgroundColor: "#D0E1E9",
|
||||
...(column.id === "action" && {
|
||||
position: "sticky",
|
||||
right: 0,
|
||||
zIndex: 2,
|
||||
boxShadow:
|
||||
"-5px 0 5px -2px rgba(0,0,0,0.15)",
|
||||
}),
|
||||
}}
|
||||
align={column.align}
|
||||
className={
|
||||
column.id === "action"
|
||||
? "action-cell"
|
||||
: undefined
|
||||
} // Add action-cell class
|
||||
>
|
||||
{column.id === "action" ? (
|
||||
<>
|
||||
<Box>
|
||||
<CustomIconButton
|
||||
onClick={() => {
|
||||
setSelectedRow(row);
|
||||
setViewModal(true);
|
||||
}}
|
||||
>
|
||||
<VisibilityIcon
|
||||
sx={{
|
||||
color: "#454545",
|
||||
"&:hover": {
|
||||
color: "#6B7280",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</CustomIconButton>
|
||||
|
||||
<CustomIconButton
|
||||
onClick={() =>
|
||||
handleEditButton(
|
||||
onClick={(e) =>
|
||||
handleMenuOpen(
|
||||
e,
|
||||
row
|
||||
)
|
||||
}
|
||||
>
|
||||
<EditIcon
|
||||
sx={{
|
||||
sx={{
|
||||
color: "#6B7280",
|
||||
"&:hover": {
|
||||
color: "#454545",
|
||||
"&:hover": {
|
||||
color: "#6B7280",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</CustomIconButton>
|
||||
|
||||
<CustomIconButton
|
||||
onClick={() => {
|
||||
setDeleteModal(
|
||||
true
|
||||
);
|
||||
setSelectedRow(row);
|
||||
},
|
||||
transition:
|
||||
"color 0.2s ease",
|
||||
}}
|
||||
>
|
||||
<DeleteIcon
|
||||
sx={{
|
||||
color: "#454545",
|
||||
"&:hover": {
|
||||
color: "#6B7280",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<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
|
||||
sx={{
|
||||
fontSize:
|
||||
"18px",
|
||||
color: "#454545",
|
||||
}}
|
||||
/>
|
||||
View
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
handleMenuAction(
|
||||
"edit"
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
color: "#000000",
|
||||
fontSize:
|
||||
"16px",
|
||||
display: "flex",
|
||||
alignItems:
|
||||
"center",
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<EditIcon
|
||||
sx={{
|
||||
fontSize:
|
||||
"18px",
|
||||
color: "#454545",
|
||||
}}
|
||||
/>
|
||||
Edit
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() =>
|
||||
handleMenuAction(
|
||||
"delete"
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
color: "#000000",
|
||||
fontSize:
|
||||
"14px",
|
||||
display: "flex",
|
||||
alignItems:
|
||||
"center",
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<DeleteIcon
|
||||
sx={{
|
||||
fontSize:
|
||||
"18px",
|
||||
color: "#454545",
|
||||
}}
|
||||
/>
|
||||
Delete
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</Box>
|
||||
) : row.statusField &&
|
||||
column.id === row.statusField ? ( // Check if statusField matches the column
|
||||
column.id === row.statusField ? (
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={(e) => {
|
||||
|
@ -548,26 +735,25 @@ const handleToggleStatus = () => {
|
|||
handleStatusToggle?.(
|
||||
row.id,
|
||||
!row.statusValue
|
||||
); // Toggle the opposite of current statusValue
|
||||
);
|
||||
}}
|
||||
color="primary"
|
||||
sx={{
|
||||
justifyContent:
|
||||
"flex-start",
|
||||
py: 0.5,
|
||||
px: 1.5,
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: "600",
|
||||
borderRadius: "4px",
|
||||
color: "#000000",
|
||||
border: "1px solid #000000",
|
||||
backgroundColor:
|
||||
"transparent",
|
||||
fontSize: "12px",
|
||||
fontWeight: 600,
|
||||
borderRadius: "6px",
|
||||
color: row.statusValue
|
||||
? "#10B981"
|
||||
: "#EF4444",
|
||||
borderColor:
|
||||
row.statusValue
|
||||
? "#10B981"
|
||||
: "#EF4444",
|
||||
padding: "4px 12px",
|
||||
"&:hover": {
|
||||
borderColor:
|
||||
"#000000",
|
||||
backgroundColor:
|
||||
"transparent",
|
||||
row.statusValue
|
||||
? "rgba(16, 185, 129, 0.1)"
|
||||
: "rgba(239, 68, 68, 0.1)",
|
||||
},
|
||||
"&::before": {
|
||||
content: '""',
|
||||
|
@ -580,7 +766,7 @@ const handleToggleStatus = () => {
|
|||
backgroundColor:
|
||||
row.statusValue
|
||||
? "#10B981"
|
||||
: "#EF4444", // Green for true, red for false
|
||||
: "#EF4444",
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
@ -593,8 +779,8 @@ const handleToggleStatus = () => {
|
|||
src={row[column.id]}
|
||||
alt="Row"
|
||||
style={{
|
||||
width: "50px",
|
||||
height: "50px",
|
||||
width: "40px",
|
||||
height: "40px",
|
||||
borderRadius: "50%",
|
||||
objectFit: "cover",
|
||||
}}
|
||||
|
@ -609,7 +795,8 @@ const handleToggleStatus = () => {
|
|||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</StyledTableContainer>
|
||||
|
||||
{/* Pagination */}
|
||||
<Box sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}>
|
||||
<Pagination
|
||||
|
@ -618,16 +805,21 @@ const handleToggleStatus = () => {
|
|||
onChange={handlePageChange}
|
||||
sx={{
|
||||
"& .MuiPaginationItem-root": {
|
||||
color: "#000000",
|
||||
color: "#1A1A1A",
|
||||
fontSize: "16px",
|
||||
},
|
||||
"& .Mui-selected": {
|
||||
backgroundColor: "#000000",
|
||||
color: "#FFFFFF",
|
||||
"&:hover": {
|
||||
backgroundColor: "#000000",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Modals */}
|
||||
{viewModal && tableType === "admin" && (
|
||||
<ViewModal
|
||||
handleView={() => handleViewButton(selectedRow?.id)}
|
||||
|
@ -644,7 +836,6 @@ const handleToggleStatus = () => {
|
|||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{viewModal && tableType === "vehicle" && (
|
||||
<VehicleViewModal
|
||||
handleView={() => handleViewButton(selectedRow?.id)}
|
||||
|
@ -669,26 +860,6 @@ const handleToggleStatus = () => {
|
|||
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
|
||||
handleDelete={() => handleDeleteButton(selectedRow?.id)}
|
||||
|
|
|
@ -10,7 +10,7 @@ import CloseIcon from "@mui/icons-material/Close";
|
|||
import { useForm, Controller } from "react-hook-form";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { managerList, updateManager } from "../../redux/slices/managerSlice.ts"; // Import the updateManager action
|
||||
import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css";// Custom styled components
|
||||
import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; // Custom styled components
|
||||
import { AppDispatch } from "../../redux/store/store.ts";
|
||||
|
||||
interface EditManagerModalProps {
|
||||
|
@ -114,7 +114,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
|
@ -128,7 +128,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" fontWeight={600}>
|
||||
<Typography variant="h6" fontWeight={600} color="#D0E1E9">
|
||||
Edit Manager
|
||||
</Typography>
|
||||
<CustomIconButton onClick={handleClose}>
|
||||
|
@ -143,7 +143,12 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}>
|
||||
{/* Manager Name */}
|
||||
<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
|
||||
</Typography>
|
||||
<Controller
|
||||
|
@ -172,7 +177,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
placeholder="Enter Manager Name"
|
||||
size="small"
|
||||
sx={{ marginTop: 1 }}
|
||||
|
||||
error={!!errors.name}
|
||||
helperText={errors.name?.message}
|
||||
/>
|
||||
|
@ -182,13 +186,25 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
|
||||
{/* Email */}
|
||||
<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
|
||||
</Typography>
|
||||
<Controller
|
||||
name="email"
|
||||
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 }) => (
|
||||
<CustomTextField
|
||||
{...field}
|
||||
|
@ -196,7 +212,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
placeholder="Enter Email"
|
||||
size="small"
|
||||
sx={{ marginTop: 1 }}
|
||||
|
||||
error={!!errors.email}
|
||||
helperText={errors.email?.message}
|
||||
/>
|
||||
|
@ -206,7 +221,12 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
|
||||
{/* Phone Number */}
|
||||
<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
|
||||
</Typography>
|
||||
<Controller
|
||||
|
@ -234,7 +254,6 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
placeholder="Enter Phone Number"
|
||||
size="small"
|
||||
sx={{ marginTop: 1 }}
|
||||
|
||||
error={!!errors.phone}
|
||||
helperText={errors.phone?.message}
|
||||
/>
|
||||
|
@ -250,11 +269,11 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
<Button
|
||||
type="submit"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#000000",
|
||||
borderRadius: "8px",
|
||||
width: "117px",
|
||||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
width: "125px",
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
whiteSpace: "pre",
|
||||
}}
|
||||
disabled={loading}
|
||||
|
|
|
@ -55,6 +55,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
setValue,
|
||||
reset,
|
||||
formState: { errors },
|
||||
register,
|
||||
} = useForm<FormData>({
|
||||
defaultValues: {
|
||||
name: "",
|
||||
|
@ -197,7 +198,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
boxShadow: 24,
|
||||
p: 3,
|
||||
borderRadius: 2,
|
||||
|
@ -211,7 +212,12 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
fontWeight={600}
|
||||
fontSize={"16px"}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Edit Charging Station
|
||||
</Typography>
|
||||
<CustomIconButton onClick={handleClose}>
|
||||
|
@ -237,6 +243,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Station Name
|
||||
</Typography>
|
||||
|
@ -256,6 +263,20 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
? 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"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Station Location
|
||||
</Typography>
|
||||
|
@ -291,6 +313,10 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
.message
|
||||
: ""
|
||||
}
|
||||
{...register("registeredAddress", {
|
||||
required:
|
||||
"Station Location is required",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
@ -310,6 +336,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
variant="body2"
|
||||
fontWeight={500}
|
||||
mb={0.5}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Total Slots
|
||||
</Typography>
|
||||
|
@ -330,6 +357,15 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
? 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%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Select Vehicle Brands
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
|
@ -385,6 +425,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
<Typography
|
||||
key={index}
|
||||
variant="body2"
|
||||
color="#454545"
|
||||
>
|
||||
{brand
|
||||
? brand.name
|
||||
|
@ -396,7 +437,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
{moreCount > 0 && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
color="#454545"
|
||||
>
|
||||
+{moreCount} more
|
||||
</Typography>
|
||||
|
@ -438,7 +479,11 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
<Typography
|
||||
variant="body2"
|
||||
fontWeight={500}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
Vehicle Name
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
|
@ -471,6 +516,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
<Typography
|
||||
key={index}
|
||||
variant="body2"
|
||||
color="#454545"
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
|
@ -479,7 +525,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
{moreCount > 0 && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="textSecondary"
|
||||
color="#454545"
|
||||
>
|
||||
+{moreCount} more
|
||||
</Typography>
|
||||
|
@ -528,12 +574,12 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
<Button
|
||||
type="submit"
|
||||
sx={{
|
||||
backgroundColor: "#52ACDF",
|
||||
color: "white",
|
||||
backgroundColor: "#D0E1E9",
|
||||
color: "#000000",
|
||||
borderRadius: "8px",
|
||||
fontSize:"16px",
|
||||
width: "117px",
|
||||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
fontSize: "16px",
|
||||
width: "150px",
|
||||
"&:hover": { backgroundColor: "#DFECF1" },
|
||||
}}
|
||||
>
|
||||
Update Station
|
||||
|
|
|
@ -15,14 +15,27 @@ const style = {
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 330,
|
||||
bgcolor: "#272727",
|
||||
bgcolor: "#000000",
|
||||
color: "#D0E1E9",
|
||||
borderRadius: 1.5,
|
||||
boxShadow: 24,
|
||||
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({
|
||||
open,
|
||||
setDeleteModal,
|
||||
|
@ -52,8 +65,9 @@ export default function DeleteModal({
|
|||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
justifyContent: "flex-end",
|
||||
marginTop: -3.5,
|
||||
|
||||
}}
|
||||
>
|
||||
<CustomIconButton
|
||||
|
@ -89,10 +103,10 @@ export default function DeleteModal({
|
|||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
type="button"
|
||||
color="primary"
|
||||
sx={btnStyle}
|
||||
variant="contained"
|
||||
color="error"
|
||||
sx={btnStyleCancel}
|
||||
onClick={() => handleDelete(id || "")}
|
||||
>
|
||||
Delete
|
||||
|
|
|
@ -18,7 +18,7 @@ const style = {
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
borderRadius: 2,
|
||||
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
||||
p: 4,
|
||||
|
@ -62,7 +62,10 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
|
|||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1, textAlign: "center" }}>
|
||||
<Box
|
||||
sx={{ flex: 1, textAlign: "center" }}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
{selectedStation?.name || "Station"}'s Details
|
||||
</Box>
|
||||
<CustomIconButton
|
||||
|
@ -79,33 +82,33 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
|
|||
{selectedStation ? (
|
||||
<Grid container spacing={2} sx={{ width: "80%" }}>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Station Name:</strong>{" "}
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedStation.name}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Station Location:</strong>{" "}
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedStation.registeredAddress}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Total Slots:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedStation.totalSlots}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Status:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedStation.status === 1
|
||||
? "Available"
|
||||
: "Not Available"}
|
||||
|
@ -115,7 +118,7 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
|
|||
|
||||
{/* Display Vehicles */}
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Vehicles:</strong>
|
||||
</Typography>
|
||||
<Box
|
||||
|
@ -125,6 +128,7 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
|
|||
gap: 1,
|
||||
marginTop: 1,
|
||||
}}
|
||||
color="#D0E1E9"
|
||||
>
|
||||
{selectedStation.allowedCars &&
|
||||
selectedStation.allowedCars.length > 0 ? (
|
||||
|
@ -138,15 +142,13 @@ export default function StationViewModal({ open, setViewModal, id }: Props) {
|
|||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{car.name}{","}
|
||||
{car.name}
|
||||
{","}
|
||||
</Typography>
|
||||
)
|
||||
)
|
||||
) : (
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
>
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
No vehicles available
|
||||
</Typography>
|
||||
)}
|
||||
|
|
|
@ -17,7 +17,7 @@ const style = {
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
borderRadius: 2,
|
||||
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
||||
p: 4,
|
||||
|
@ -61,7 +61,13 @@ export default function VehicleViewModal({ open, setViewModal, id }: Props) {
|
|||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1, textAlign: "center" }}>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
textAlign: "center",
|
||||
color: "#D0E1E9",
|
||||
}}
|
||||
>
|
||||
{selectedVehicle?.name || "Vehicle"}'s Details
|
||||
</Box>
|
||||
<Box
|
||||
|
@ -82,39 +88,43 @@ export default function VehicleViewModal({ open, setViewModal, id }: Props) {
|
|||
{selectedVehicle ? (
|
||||
<Grid container spacing={2} sx={{ width: "80%" }}>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Name:</strong>{" "}
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedVehicle.name}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Company:</strong>{" "}
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedVehicle.company}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Model Name:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedVehicle.modelName}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Charge Type:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedVehicle.chargeType}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="body1" gutterBottom>
|
||||
<Typography
|
||||
variant="body1"
|
||||
gutterBottom
|
||||
color="#D0E1E9"
|
||||
>
|
||||
<strong>Image:</strong>
|
||||
</Typography>
|
||||
{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
|
||||
</Typography>
|
||||
)}
|
||||
|
|
|
@ -17,7 +17,7 @@ const style = {
|
|||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: 400,
|
||||
bgcolor: "background.paper",
|
||||
bgcolor: "#000000",
|
||||
borderRadius: 2,
|
||||
boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)",
|
||||
p: 4,
|
||||
|
@ -32,10 +32,9 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
(state: RootState) => state.managerReducer
|
||||
);
|
||||
const [selectedManager, setSelectedManager] = useState<any>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
|
||||
const manager = managers.find((manager) => manager.id === id);
|
||||
setSelectedManager(manager || null);
|
||||
}
|
||||
|
@ -62,7 +61,13 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1, textAlign: "center" }}>
|
||||
<Box
|
||||
sx={{
|
||||
flex: 1,
|
||||
textAlign: "center",
|
||||
color: "#D0E1E9",
|
||||
}}
|
||||
>
|
||||
{selectedManager?.name || "Manager"}'s Details
|
||||
</Box>
|
||||
<Box
|
||||
|
@ -71,6 +76,7 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
cursor: "pointer",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
color: "#D0E1E9",
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
|
@ -83,42 +89,42 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
{selectedManager ? (
|
||||
<Grid container spacing={2} sx={{ width: "80%" }}>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Name:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedManager.name}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Email:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedManager.email}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Phone:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedManager.phone}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Station Location:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedManager.chargingStation
|
||||
?.registeredAddress || "Not Available"}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={6}>
|
||||
<Typography variant="body1">
|
||||
<Typography variant="body1" color="#D0E1E9">
|
||||
<strong>Station Name:</strong>
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" color="#D0E1E9">
|
||||
{selectedManager.chargingStation?.name ||
|
||||
"Not Available"}
|
||||
</Typography>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import * as React from "react";
|
||||
import { ThemeProvider, Theme, createTheme } 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
|
||||
},
|
||||
text: {
|
||||
primary: "#000000", // Already matches the image
|
||||
primary: "#454545", // Already matches the image
|
||||
secondary: "#272727", // Already matches the image
|
||||
},
|
||||
success: {
|
||||
|
@ -55,6 +54,7 @@ export default function AppTheme(props: AppThemeProps) {
|
|||
body2: {
|
||||
fontSize: "0.875rem",
|
||||
color: "#b0b0b0",
|
||||
fontWeight: 300,
|
||||
},
|
||||
},
|
||||
cssVariables: {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export const autofillFix = {
|
||||
"& input:-webkit-autofill": {
|
||||
WebkitBoxShadow: "0 0 0 1000px transparent inset !important",
|
||||
WebkitTextFillColor: "white !important",
|
||||
WebkitTextFillColor: "#454545 !important",
|
||||
transition: "background-color 5000s ease-in-out 0s",
|
||||
},
|
||||
"& input:-webkit-autofill:hover": {
|
||||
|
@ -15,12 +15,12 @@ export const autofillFix = {
|
|||
},
|
||||
"& input:-moz-autofill": {
|
||||
boxShadow: "0 0 0 1000px transparent inset !important",
|
||||
MozTextFillColor: "white !important",
|
||||
MozTextFillColor: "#454545 !important",
|
||||
transition: "background-color 5000s ease-in-out 0s",
|
||||
},
|
||||
"& input:autofill": {
|
||||
boxShadow: "0 0 0 1000px transparent inset !important",
|
||||
textFillColor: "transparent !important",
|
||||
textFillColor: "#454545 !important",
|
||||
transition: "background-color 5000s ease-in-out 0s",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -385,7 +385,7 @@ export const inputsCustomizations: Components<Theme> = {
|
|||
input: {
|
||||
"&::placeholder": {
|
||||
opacity: 0.7,
|
||||
color: gray[500],
|
||||
color: gray[600],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue