dev-jaanvi #1
162
src/components/AddManagerStationModal/addmanagerStationModal.tsx
Normal file
162
src/components/AddManagerStationModal/addmanagerStationModal.tsx
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Modal,
|
||||||
|
TextField,
|
||||||
|
FormControlLabel,
|
||||||
|
Switch,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import { addStationDetails } from "../../redux/slices/managerStationSlice"; // Updated import
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { CustomIconButton } from "../AddUserModal/styled.css";
|
||||||
|
|
||||||
|
const AddManagerStationModal = ({ open, handleClose }: any) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm();
|
||||||
|
|
||||||
|
const [isAvailable, setIsAvailable] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const onSubmit = (data: any) => {
|
||||||
|
const { connectorType, power, price } = data;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
connectorType,
|
||||||
|
power,
|
||||||
|
price,
|
||||||
|
isAvailable,
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(addStationDetails(payload));
|
||||||
|
reset();
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
onClose={(e, reason) => {
|
||||||
|
if (reason === "backdropClick") return;
|
||||||
|
handleClose();
|
||||||
|
}}
|
||||||
|
aria-labelledby="add-manager-modal"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: 400,
|
||||||
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 3,
|
||||||
|
borderRadius: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||||
|
Add Manager Station
|
||||||
|
</Typography>
|
||||||
|
<CustomIconButton onClick={handleClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</CustomIconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Divider */}
|
||||||
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||||
|
|
||||||
|
{/* Connector Type */}
|
||||||
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||||
|
Connector Type
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
{...register("connectorType", {
|
||||||
|
required: "Connector Type is required",
|
||||||
|
})}
|
||||||
|
fullWidth
|
||||||
|
error={!!errors.connectorType}
|
||||||
|
helperText={errors.connectorType?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Power */}
|
||||||
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||||
|
Power (kW)
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
{...register("power", { required: "Power is required" })}
|
||||||
|
fullWidth
|
||||||
|
error={!!errors.power}
|
||||||
|
helperText={errors.power?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Price */}
|
||||||
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||||
|
Price (₹)
|
||||||
|
</Typography>
|
||||||
|
<TextField
|
||||||
|
{...register("price", {
|
||||||
|
required: "Price is required",
|
||||||
|
pattern: {
|
||||||
|
value: /^[0-9]+$/,
|
||||||
|
message: "Price must be a number",
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
fullWidth
|
||||||
|
error={!!errors.price}
|
||||||
|
helperText={errors.price?.message}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Availability Switch */}
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={isAvailable}
|
||||||
|
onChange={() => setIsAvailable((prev) => !prev)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={isAvailable ? "Available" : "Not Available"}
|
||||||
|
sx={{ mt: 2 }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Submit */}
|
||||||
|
<Box
|
||||||
|
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
fontSize: "16px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Station
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddManagerStationModal;
|
|
@ -43,16 +43,29 @@ import {
|
||||||
import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts";
|
import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts";
|
||||||
import AddCircleIcon from "@mui/icons-material/AddCircle";
|
import AddCircleIcon from "@mui/icons-material/AddCircle";
|
||||||
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";
|
||||||
|
import { deleteStationDetails, stationDetailList } from "../../redux/slices/managerStationSlice.ts";
|
||||||
|
import ManagerStationDetails from "../../pages/ManagerStationDetails/index.tsx";
|
||||||
// Styled components for customization
|
// Styled components for customization
|
||||||
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
const StyledTableCell = styled(TableCell)(({ theme }) => ({
|
||||||
[`&.${tableCellClasses.head}`]: {
|
|
||||||
backgroundColor: "#454545", // Changed to #272727 for the header
|
|
||||||
color: theme.palette.common.white,
|
|
||||||
borderBottom: "none", // Remove any border at the bottom of the header
|
|
||||||
},
|
|
||||||
[`&.${tableCellClasses.body}`]: {
|
[`&.${tableCellClasses.body}`]: {
|
||||||
fontSize: "16px",
|
fontSize: "16px",
|
||||||
borderBottom: "1px solid #454545", // Adding border to body cells
|
borderBottom: "1px solid #454545",
|
||||||
|
|
||||||
|
},
|
||||||
|
[`&.${tableCellClasses.head}`]: {
|
||||||
|
backgroundColor: "#454545",
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
borderBottom: "none",
|
||||||
|
borderRight: "1px solid rgba(141, 135, 135, 0.51)",
|
||||||
|
// transition: "border-color 0.3s ease",
|
||||||
|
position: "sticky",
|
||||||
|
top: 0,
|
||||||
|
zIndex: 10,
|
||||||
|
// "&:hover": {
|
||||||
|
// borderRight: "3px solid rgba(112, 109, 109, 0.8)",
|
||||||
|
// },p
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -116,6 +129,9 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
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 open = Boolean(anchorEl);
|
||||||
|
const [sortOrder, setSortOrder] = React.useState<"asc" | "desc" | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
const handleClick = (event: React.MouseEvent<HTMLElement>, row: Row) => {
|
const handleClick = (event: React.MouseEvent<HTMLElement>, row: Row) => {
|
||||||
setAnchorEl(event.currentTarget);
|
setAnchorEl(event.currentTarget);
|
||||||
setSelectedRow(row);
|
setSelectedRow(row);
|
||||||
|
@ -161,6 +177,10 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
case "booking":
|
case "booking":
|
||||||
dispatch(deleteBooking(id || ""));
|
dispatch(deleteBooking(id || ""));
|
||||||
break;
|
break;
|
||||||
|
case "manager-station":
|
||||||
|
dispatch(deleteStationDetails(id || ""));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.error("Unknown table type:", tableType);
|
console.error("Unknown table type:", tableType);
|
||||||
return;
|
return;
|
||||||
|
@ -193,6 +213,9 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
case "station":
|
case "station":
|
||||||
dispatch(stationList());
|
dispatch(stationList());
|
||||||
break;
|
break;
|
||||||
|
case "manager-station":
|
||||||
|
dispatch(stationDetailList());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.error("Unknown table type:", tableType);
|
console.error("Unknown table type:", tableType);
|
||||||
return;
|
return;
|
||||||
|
@ -210,15 +233,37 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
handleClose();
|
handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const filteredRows = rows.filter((row) => {
|
const handleSort = () => {
|
||||||
if (!searchQuery.trim()) return true; // Return all rows if searchQuery is empty or whitespace
|
setSortOrder((prevSortOrder) =>
|
||||||
const lowerCaseQuery = searchQuery.toLowerCase().trim();
|
prevSortOrder === "asc" ? "desc" : "asc"
|
||||||
return (
|
|
||||||
(row.name && row.name.toLowerCase().includes(lowerCaseQuery)) ||
|
|
||||||
(row.registeredAddress &&
|
|
||||||
row.registeredAddress.toLowerCase().includes(lowerCaseQuery))
|
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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 indexOfLastRow = currentPage * usersPerPage;
|
||||||
const indexOfFirstRow = indexOfLastRow - usersPerPage;
|
const indexOfFirstRow = indexOfLastRow - usersPerPage;
|
||||||
|
@ -278,6 +323,8 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
return "Slots";
|
return "Slots";
|
||||||
case "all-available-slots":
|
case "all-available-slots":
|
||||||
return "Available Slots";
|
return "Available Slots";
|
||||||
|
case "manager-station":
|
||||||
|
return "Station Details"
|
||||||
default:
|
default:
|
||||||
return "List";
|
return "List";
|
||||||
}
|
}
|
||||||
|
@ -293,7 +340,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
marginTop: "16px",
|
marginTop: "16px",
|
||||||
alignItems: { xs: "stretch", sm: "stretch", md: "center" },
|
alignItems: { xs: "stretch", sm: "stretch", md: "center" },
|
||||||
width: "100%",
|
width: "100%",
|
||||||
...autofillFix
|
...autofillFix,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
|
@ -358,7 +405,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
maxWidth: "250px", // Optional: limit it from being *too* wide
|
maxWidth: "250px", // Optional: limit it from being *too* wide
|
||||||
marginRight: "16px",
|
marginRight: "16px",
|
||||||
paddingX: "16px",
|
paddingX: "16px",
|
||||||
fontSize:"16px",
|
fontSize: "16px",
|
||||||
whiteSpace: "nowrap", // Prevents text from wrapping
|
whiteSpace: "nowrap", // Prevents text from wrapping
|
||||||
"&:hover": { backgroundColor: "#439BC1" },
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
}}
|
}}
|
||||||
|
@ -386,6 +433,8 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
return "Slot";
|
return "Slot";
|
||||||
case "external-station":
|
case "external-station":
|
||||||
return "Location";
|
return "Location";
|
||||||
|
case "manager-station":
|
||||||
|
return "Station Details"
|
||||||
default:
|
default:
|
||||||
return "Item";
|
return "Item";
|
||||||
}
|
}
|
||||||
|
@ -430,6 +479,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
<Table sx={{ minWidth: "750px", tableLayout: "auto" }}>
|
<Table sx={{ minWidth: "750px", tableLayout: "auto" }}>
|
||||||
<TableHead
|
<TableHead
|
||||||
|
@ -442,6 +492,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
borderBottom: "1px solid #454545",
|
borderBottom: "1px solid #454545",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
>
|
>
|
||||||
{" "}
|
{" "}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
@ -464,6 +515,34 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{column.label}
|
{column.label}
|
||||||
|
{column.id === "name" && (
|
||||||
|
<CustomIconButton
|
||||||
|
onClick={handleSort}
|
||||||
|
sx={{
|
||||||
|
marginLeft: "8px",
|
||||||
|
opacity: 0.4, // Initial transparency
|
||||||
|
transition:
|
||||||
|
"0px 0px 0px rgba(255, 255, 255, 0)",
|
||||||
|
"&:hover": {
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
"&:active": {
|
||||||
|
opacity: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{sortOrder === "asc" ? (
|
||||||
|
<ArrowUpwardIcon
|
||||||
|
sx={{ color: "#FFFFFF" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ArrowDownwardIcon
|
||||||
|
sx={{ color: "#FFFFFF" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</CustomIconButton>
|
||||||
|
)}
|
||||||
</StyledTableCell>
|
</StyledTableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
@ -613,7 +692,7 @@ const CustomTable: React.FC<CustomTableProps> = ({
|
||||||
"& .MuiPaginationItem-page.Mui-selected": {
|
"& .MuiPaginationItem-page.Mui-selected": {
|
||||||
backgroundColor: "transparent",
|
backgroundColor: "transparent",
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
fontSize:"16px",
|
fontSize: "16px",
|
||||||
color: "#FFFFFF",
|
color: "#FFFFFF",
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Typography,
|
||||||
|
Modal,
|
||||||
|
CircularProgress,
|
||||||
|
} from "@mui/material";
|
||||||
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { useForm, Controller } from "react-hook-form";
|
||||||
|
import { useDispatch } from "react-redux";
|
||||||
|
import {
|
||||||
|
updateSlot,
|
||||||
|
fetchManagersSlots,
|
||||||
|
} from "../../redux/slices/slotSlice.ts"; // Update with correct action
|
||||||
|
import { CustomIconButton, CustomTextField } from "../AddUserModal/styled.css"; // Custom styled components
|
||||||
|
import { AppDispatch } from "../../redux/store/store.ts";
|
||||||
|
|
||||||
|
// Defining props for the modal
|
||||||
|
interface EditManagerStationModalProp {
|
||||||
|
open: boolean;
|
||||||
|
handleClose: () => void;
|
||||||
|
editRow: any; // Slot data including id
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FormData {
|
||||||
|
startTime: string;
|
||||||
|
endTime: string;
|
||||||
|
isAvailable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditSlotModal: React.FC<EditManagerStationModalProp> = ({
|
||||||
|
open,
|
||||||
|
handleClose,
|
||||||
|
editRow,
|
||||||
|
}) => {
|
||||||
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
|
const {
|
||||||
|
control,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors },
|
||||||
|
setValue,
|
||||||
|
reset,
|
||||||
|
} = useForm<FormData>({
|
||||||
|
defaultValues: {
|
||||||
|
startTime: "",
|
||||||
|
endTime: "",
|
||||||
|
isAvailable: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [isAvailable, setIsAvailable] = useState<boolean>(
|
||||||
|
editRow?.isAvailable || false
|
||||||
|
);
|
||||||
|
|
||||||
|
// Effect to prepopulate the form when the modal is opened
|
||||||
|
useEffect(() => {
|
||||||
|
if (editRow) {
|
||||||
|
setValue("startTime", editRow.startTime);
|
||||||
|
setValue("endTime", editRow.endTime);
|
||||||
|
setIsAvailable(editRow.isAvailable);
|
||||||
|
} else {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}, [editRow, setValue, reset]);
|
||||||
|
|
||||||
|
// Handle form submission
|
||||||
|
const onSubmit = async (data: FormData) => {
|
||||||
|
if (editRow) {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const availabilityStatus = isAvailable ? true : false;
|
||||||
|
|
||||||
|
// Dispatching the update action to the Redux slice
|
||||||
|
await dispatch(
|
||||||
|
updateSlot({
|
||||||
|
id: editRow.id, // Slot ID from the editRow object
|
||||||
|
startTime: data.startTime,
|
||||||
|
endTime: data.endTime,
|
||||||
|
isAvailable: availabilityStatus,
|
||||||
|
})
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
// Fetch the updated slots after updating the slot
|
||||||
|
dispatch(fetchManagersSlots());
|
||||||
|
|
||||||
|
// Close the modal after successful submission
|
||||||
|
handleClose();
|
||||||
|
reset(); // Reset the form
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating slot:", error);
|
||||||
|
// Handle error if needed (e.g., show toast notification)
|
||||||
|
} finally {
|
||||||
|
setLoading(false); // Stop loading state after completion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
open={open}
|
||||||
|
onClose={(e, reason) => {
|
||||||
|
if (reason === "backdropClick") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handleClose(); // Close modal when clicking cross or cancel
|
||||||
|
}}
|
||||||
|
aria-labelledby="edit-slot-modal"
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
component="form"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: 400,
|
||||||
|
bgcolor: "background.paper",
|
||||||
|
boxShadow: 24,
|
||||||
|
p: 3,
|
||||||
|
borderRadius: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* Header */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" fontWeight={600} fontSize={"16px"}>
|
||||||
|
Edit Slot
|
||||||
|
</Typography>
|
||||||
|
<CustomIconButton onClick={handleClose}>
|
||||||
|
<CloseIcon />
|
||||||
|
</CustomIconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Horizontal Line */}
|
||||||
|
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||||
|
|
||||||
|
{/* Input Fields */}
|
||||||
|
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}>
|
||||||
|
{/* Start Time */}
|
||||||
|
<Box sx={{ flex: "1 1 48%" }}>
|
||||||
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||||
|
Start Time
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="startTime"
|
||||||
|
control={control}
|
||||||
|
rules={{ required: "Start Time is required" }}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
type="time"
|
||||||
|
fullWidth
|
||||||
|
size="small"
|
||||||
|
error={!!errors.startTime}
|
||||||
|
helperText={errors.startTime?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* End Time */}
|
||||||
|
<Box sx={{ flex: "1 1 48%" }}>
|
||||||
|
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||||
|
End Time
|
||||||
|
</Typography>
|
||||||
|
<Controller
|
||||||
|
name="endTime"
|
||||||
|
control={control}
|
||||||
|
rules={{ required: "End Time is required" }}
|
||||||
|
render={({ field }) => (
|
||||||
|
<CustomTextField
|
||||||
|
{...field}
|
||||||
|
type="time"
|
||||||
|
fullWidth
|
||||||
|
size="small"
|
||||||
|
error={!!errors.endTime}
|
||||||
|
helperText={errors.endTime?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Availability Toggle */}
|
||||||
|
<Box
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="space-between"
|
||||||
|
gap={2}
|
||||||
|
sx={{ flex: "1 1 100%" }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
const newAvailability = !isAvailable;
|
||||||
|
setIsAvailable(newAvailability); // Update local state
|
||||||
|
setValue("isAvailable", newAvailability); // Update form value for isAvailable
|
||||||
|
}}
|
||||||
|
variant={isAvailable ? "contained" : "outlined"}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
{isAvailable ? "Available" : "Not Available"}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<Box
|
||||||
|
sx={{ display: "flex", justifyContent: "flex-end", mt: 3 }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#52ACDF",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "8px",
|
||||||
|
fontSize: "16px",
|
||||||
|
width: "117px",
|
||||||
|
"&:hover": { backgroundColor: "#439BC1" },
|
||||||
|
}}
|
||||||
|
disabled={loading} // Disable the button during loading state
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} color="inherit" />
|
||||||
|
) : (
|
||||||
|
"Update Slot"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditSlotModal;
|
|
@ -59,6 +59,10 @@ export default function Header() {
|
||||||
boxSizing: "border-box",
|
boxSizing: "border-box",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
flex: "0 0 84px",
|
flex: "0 0 84px",
|
||||||
|
position: "fixed",
|
||||||
|
top: "0",
|
||||||
|
left: "0",
|
||||||
|
zIndex: 1000,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack
|
<Stack
|
||||||
|
|
|
@ -86,7 +86,11 @@ export default function MenuContent({ hidden }: PropType) {
|
||||||
icon: <ChecklistSharpIcon />,
|
icon: <ChecklistSharpIcon />,
|
||||||
url: "/panel/slot-list", // Placeholder for now
|
url: "/panel/slot-list", // Placeholder for now
|
||||||
},
|
},
|
||||||
|
userRole === "manager" && {
|
||||||
|
text: "Station Details",
|
||||||
|
icon: <ChecklistSharpIcon />,
|
||||||
|
url: "/panel/manager-station-details", // Placeholder for now
|
||||||
|
},
|
||||||
userRole === "user" && {
|
userRole === "user" && {
|
||||||
text: "Available Slots",
|
text: "Available Slots",
|
||||||
icon: <ChecklistSharpIcon />,
|
icon: <ChecklistSharpIcon />,
|
||||||
|
|
|
@ -21,7 +21,7 @@ export default function EVSlotList() {
|
||||||
dispatch(fetchAvailableSlots());
|
dispatch(fetchAvailableSlots());
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
|
console.log("first", availableSlots);
|
||||||
|
|
||||||
const slotColumns: Column[] = [
|
const slotColumns: Column[] = [
|
||||||
{ id: "srno", label: "Sr No" },
|
{ id: "srno", label: "Sr No" },
|
||||||
|
@ -36,18 +36,33 @@ export default function EVSlotList() {
|
||||||
|
|
||||||
const slotRows = availableSlots?.length
|
const slotRows = availableSlots?.length
|
||||||
? availableSlots.map((slot, index) => {
|
? availableSlots.map((slot, index) => {
|
||||||
const formattedDate = dayjs(slot?.date).format("YYYY-MM-DD");
|
// const formattedDate = dayjs(slot?.date).format("YYYY-MM-DD");
|
||||||
const startTime = dayjs(slot?.startTime).format("HH:mm");
|
// const startTime = dayjs(
|
||||||
const endTime = dayjs(slot?.endTime).format("HH:mm");
|
// slot?.startTime,
|
||||||
|
// "YYYY-MM-DD hh:mm A"
|
||||||
|
// ).isValid()
|
||||||
|
// ? dayjs(slot?.startTime, "YYYY-MM-DD hh:mm A").format(
|
||||||
|
// "hh:mm A"
|
||||||
|
// )
|
||||||
|
// : "Invalid";
|
||||||
|
|
||||||
|
// const endTime = dayjs(
|
||||||
|
// slot?.endTime,
|
||||||
|
// "YYYY-MM-DD hh:mm A"
|
||||||
|
// ).isValid()
|
||||||
|
// ? dayjs(slot?.endTime, "YYYY-MM-DD hh:mm A").format(
|
||||||
|
// "hh:mm A"
|
||||||
|
// )
|
||||||
|
// : "Invalid";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
srno: index + 1,
|
srno: index + 1,
|
||||||
id: slot?.id ?? "NA",
|
id: slot?.id ?? "NA",
|
||||||
stationId: slot?.stationId ?? "NA",
|
stationId: slot?.stationId ?? "NA",
|
||||||
name: slot?.ChargingStation?.name ?? "NA",
|
name: slot?.ChargingStation?.name ?? "NA",
|
||||||
date: formattedDate ?? "NA",
|
date: slot?.date ?? "NA",
|
||||||
startTime: startTime ?? "NA",
|
startTime: slot?.startTime ?? "NA",
|
||||||
endTime: endTime ?? "NA",
|
endTime: slot?.endTime ?? "NA",
|
||||||
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
|
@ -164,7 +164,7 @@ export default function EVSlotList() {
|
||||||
|
|
||||||
const slotRows = availableSlots?.length
|
const slotRows = availableSlots?.length
|
||||||
? availableSlots.map((slot, index) => {
|
? availableSlots.map((slot, index) => {
|
||||||
const formattedDate = dayjs(slot?.date).format("YYYY-MM-DD");
|
|
||||||
const startTime = dayjs(
|
const startTime = dayjs(
|
||||||
slot?.startTime,
|
slot?.startTime,
|
||||||
"YYYY-MM-DD hh:mm A"
|
"YYYY-MM-DD hh:mm A"
|
||||||
|
@ -187,7 +187,7 @@ export default function EVSlotList() {
|
||||||
srno: index + 1,
|
srno: index + 1,
|
||||||
id: slot?.id ?? "NA",
|
id: slot?.id ?? "NA",
|
||||||
stationName: slot?.stationName ?? "NA",
|
stationName: slot?.stationName ?? "NA",
|
||||||
date: formattedDate ?? "NA",
|
date: slot?.date ?? "NA",
|
||||||
startTime: startTime ?? "NA",
|
startTime: startTime ?? "NA",
|
||||||
endTime: endTime ?? "NA",
|
endTime: endTime ?? "NA",
|
||||||
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
||||||
|
|
146
src/pages/ManagerStationDetails/index.tsx
Normal file
146
src/pages/ManagerStationDetails/index.tsx
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import CustomTable, { Column } from "../../components/CustomTable/customTable";
|
||||||
|
import AddManagerModal from "../../components/AddManagerModal/addManagerModal";
|
||||||
|
import EditManagerModal from "../../components/EditManagerModal/editManagerModal";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { RootState, AppDispatch } from "../../redux/store/store";
|
||||||
|
import {
|
||||||
|
managerList,
|
||||||
|
addManager,
|
||||||
|
updateManager,
|
||||||
|
} from "../../redux/slices/managerSlice";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import {
|
||||||
|
addStationDetails,
|
||||||
|
stationDetailList,
|
||||||
|
updateStationDetails,
|
||||||
|
} from "../../redux/slices/managerStationSlice";
|
||||||
|
import AddManagerStationModal from "../../components/AddManagerStationModal/addmanagerStationModal";
|
||||||
|
import EditManagerStationModal from "../../components/EditManagerStationModal/editManagerStationModal";
|
||||||
|
|
||||||
|
export default function ManagerStationDetails() {
|
||||||
|
const [addModalOpen, setAddModalOpen] = useState<boolean>(false);
|
||||||
|
const [editModalOpen, setEditModalOpen] = useState<boolean>(false);
|
||||||
|
const { reset } = useForm();
|
||||||
|
|
||||||
|
const [deleteModal, setDeleteModal] = useState<boolean>(false);
|
||||||
|
const [viewModal, setViewModal] = useState<boolean>(false);
|
||||||
|
const [rowData, setRowData] = useState<any | null>(null);
|
||||||
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
|
const managerStationDetails = useSelector(
|
||||||
|
(state: RootState) => state.managerStationReducer.stationDetails
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(stationDetailList());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const handleClickOpen = () => {
|
||||||
|
setRowData(null);
|
||||||
|
setAddModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setAddModalOpen(false);
|
||||||
|
setEditModalOpen(false);
|
||||||
|
setRowData(null);
|
||||||
|
reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddManager = async (data: {
|
||||||
|
stationId: string;
|
||||||
|
connectorType: string;
|
||||||
|
power: string;
|
||||||
|
price: string;
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
// Add manager with stationId
|
||||||
|
await dispatch(addStationDetails(data)); // Dispatch action to add manager
|
||||||
|
await dispatch(stationDetailList()); // Fetch the updated list
|
||||||
|
handleCloseModal(); // Close the modal
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error adding manager", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle updating an existing manager
|
||||||
|
const handleUpdate = async (
|
||||||
|
id: number,
|
||||||
|
connectorType: string,
|
||||||
|
power: string,
|
||||||
|
price: string
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
await dispatch(
|
||||||
|
updateStationDetails({
|
||||||
|
id,
|
||||||
|
connectorType,
|
||||||
|
power,
|
||||||
|
price,
|
||||||
|
isAvailable: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
await dispatch(stationDetailList());
|
||||||
|
handleCloseModal();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Update failed", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const categoryColumns: Column[] = [
|
||||||
|
{ id: "srno", label: "Sr No" },
|
||||||
|
{ id: "stationName", label: "Station Name" },
|
||||||
|
{ id: "registeredAddress", label: "Station Location" },
|
||||||
|
{ id: "connectorType", label: "Connector Type" },
|
||||||
|
{ id: "power", label: "Max Power(KW)" },
|
||||||
|
{ id: "price", label: "Price" },
|
||||||
|
{ id: "isAvailable", label: "Is Available", align: "center" },
|
||||||
|
{ id: "action", label: "Action", align: "center" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const categoryRows = managerStationDetails?.length
|
||||||
|
? managerStationDetails.map((managerStation, index) => {
|
||||||
|
return {
|
||||||
|
id: managerStation.id,
|
||||||
|
srno: index + 1,
|
||||||
|
stationName: managerStation?.stationName ?? "NA",
|
||||||
|
registeredAddress: managerStation.registeredAddress,
|
||||||
|
connectorType: managerStation.connectorType,
|
||||||
|
power: managerStation.power,
|
||||||
|
price: managerStation.price ?? "NA",
|
||||||
|
isAvailable: managerStation?.isAvailable ? "Yes" : "No",
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Custom Table to show manager list */}
|
||||||
|
<CustomTable
|
||||||
|
columns={categoryColumns}
|
||||||
|
rows={categoryRows}
|
||||||
|
setDeleteModal={setDeleteModal}
|
||||||
|
deleteModal={deleteModal}
|
||||||
|
setViewModal={setViewModal}
|
||||||
|
viewModal={viewModal}
|
||||||
|
setRowData={setRowData}
|
||||||
|
setModalOpen={() => setEditModalOpen(true)}
|
||||||
|
tableType="manager-station"
|
||||||
|
handleClickOpen={handleClickOpen}
|
||||||
|
/>
|
||||||
|
{/* Add Manager Modal */}
|
||||||
|
<AddManagerStationModal
|
||||||
|
open={addModalOpen}
|
||||||
|
handleClose={handleCloseModal}
|
||||||
|
handleAddManager={handleAddManager}
|
||||||
|
/>
|
||||||
|
{/* Edit Manager Modal */}
|
||||||
|
<EditManagerStationModal
|
||||||
|
open={editModalOpen}
|
||||||
|
handleClose={handleCloseModal}
|
||||||
|
handleUpdate={handleUpdate}
|
||||||
|
editRow={rowData}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ import stationReducer from "../redux/slices/stationSlice.ts";
|
||||||
import slotReducer from "../redux/slices/slotSlice.ts";
|
import slotReducer from "../redux/slices/slotSlice.ts";
|
||||||
import bookReducer from "../redux/slices/bookSlice.ts";
|
import bookReducer from "../redux/slices/bookSlice.ts";
|
||||||
import dashboardReducer from "../redux/slices/dashboardSlice.ts";
|
import dashboardReducer from "../redux/slices/dashboardSlice.ts";
|
||||||
|
import managerStationReducer from "../redux/slices/managerStationSlice.ts";
|
||||||
|
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
authReducer,
|
authReducer,
|
||||||
|
@ -23,8 +25,8 @@ const rootReducer = combineReducers({
|
||||||
stationReducer,
|
stationReducer,
|
||||||
slotReducer,
|
slotReducer,
|
||||||
bookReducer,
|
bookReducer,
|
||||||
dashboardReducer,
|
dashboardReducer,
|
||||||
|
managerStationReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type RootState = ReturnType<typeof rootReducer>;
|
export type RootState = ReturnType<typeof rootReducer>;
|
||||||
|
|
206
src/redux/slices/managerStationSlice.ts
Normal file
206
src/redux/slices/managerStationSlice.ts
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
import http from "../../lib/https";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface StationDetails {
|
||||||
|
id: number;
|
||||||
|
stationName: string;
|
||||||
|
registeredAddress: string;
|
||||||
|
connectorType: string;
|
||||||
|
power: string;
|
||||||
|
price: string;
|
||||||
|
isAvailable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StationDetailState {
|
||||||
|
stationDetails: StationDetails[];
|
||||||
|
loading: boolean;
|
||||||
|
error: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
const initialState: StationDetailState = {
|
||||||
|
stationDetails: [],
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fetch Manager List (Async Thunk)
|
||||||
|
export const stationDetailList = createAsyncThunk<
|
||||||
|
StationDetails[],
|
||||||
|
void,
|
||||||
|
{ rejectValue: string }
|
||||||
|
>("fetchStationsDetails", async (_, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const token = localStorage?.getItem("authToken");
|
||||||
|
if (!token) throw new Error("No token found");
|
||||||
|
|
||||||
|
const response = await http.get("/manager-station-details");
|
||||||
|
if (!response.data?.data) throw new Error("Invalid API response");
|
||||||
|
return response.data.data;
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error("Error Fetching Managers: " + error.message);
|
||||||
|
return rejectWithValue(
|
||||||
|
error?.response?.data?.message || "An error occurred"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Manager (Async Thunk)
|
||||||
|
export const addStationDetails = createAsyncThunk<
|
||||||
|
StationDetails,
|
||||||
|
{
|
||||||
|
connectorType: string;
|
||||||
|
power: string;
|
||||||
|
price: string;
|
||||||
|
isAvailable: boolean;
|
||||||
|
},
|
||||||
|
{ rejectValue: string }
|
||||||
|
>("addManager", async (data, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const response = await http.post(
|
||||||
|
"create-manager-station-details",
|
||||||
|
data
|
||||||
|
);
|
||||||
|
toast.success("Station details created successfully");
|
||||||
|
return response.data?.data;
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error("Error creating manager: " + error.response?.data?.message);
|
||||||
|
return rejectWithValue(
|
||||||
|
error.response?.data?.message || "An error occurred"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update Manager (Async Thunk)
|
||||||
|
export const updateStationDetails = createAsyncThunk<
|
||||||
|
StationDetails,
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
connectorType: string;
|
||||||
|
power: string;
|
||||||
|
price: string;
|
||||||
|
isAvailable: boolean;
|
||||||
|
},
|
||||||
|
{ rejectValue: string }
|
||||||
|
>(
|
||||||
|
"updateManagerStationDetails",
|
||||||
|
async ({ id, ...managerStationData }, { rejectWithValue }) => {
|
||||||
|
if (!id) {
|
||||||
|
return rejectWithValue("Manager ID is required.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const response = await http.put(
|
||||||
|
`/update-manager-station-details/${id}`,
|
||||||
|
{ ...managerStationData }
|
||||||
|
);
|
||||||
|
toast.success("Station Details updated successfully");
|
||||||
|
return response?.data;
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error("Error updating manager: " + error.message);
|
||||||
|
return rejectWithValue(
|
||||||
|
error.response?.data?.message || "An error occurred"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete Manager (Async Thunk)
|
||||||
|
export const deleteStationDetails = createAsyncThunk<
|
||||||
|
string,
|
||||||
|
string,
|
||||||
|
{ rejectValue: string }
|
||||||
|
>("deleteManager", async (id, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
await http.delete(`/delete-manager/${id}`);
|
||||||
|
toast.success("Station details deleted successfully!");
|
||||||
|
return id;
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error("Error deleting manager: " + error.message);
|
||||||
|
return rejectWithValue(
|
||||||
|
error.response?.data?.message || "An error occurred"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create Slice
|
||||||
|
const managerStationSlice = createSlice({
|
||||||
|
name: "manager-station",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
extraReducers: (builder) => {
|
||||||
|
builder
|
||||||
|
// Fetch Managers
|
||||||
|
.addCase(stationDetailList.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(
|
||||||
|
stationDetailList.fulfilled,
|
||||||
|
(state, action: PayloadAction<StationDetails[]>) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.stationDetails = action.payload;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.addCase(stationDetailList.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload || "Failed to fetch managers";
|
||||||
|
})
|
||||||
|
|
||||||
|
// Add Station details
|
||||||
|
.addCase(addStationDetails.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
})
|
||||||
|
.addCase(
|
||||||
|
addStationDetails.fulfilled,
|
||||||
|
(state, action: PayloadAction<StationDetails>) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.stationDetails.push(action.payload);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.addCase(addStationDetails.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload || "Failed to add manager";
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update Manager
|
||||||
|
.addCase(updateStationDetails.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
})
|
||||||
|
.addCase(updateStationDetails.fulfilled, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
const updateStationDetail = action.payload;
|
||||||
|
const index = state.stationDetails.findIndex(
|
||||||
|
(stationDetail) =>
|
||||||
|
stationDetail.id === updateStationDetail.id
|
||||||
|
);
|
||||||
|
if (index !== -1) {
|
||||||
|
state.stationDetails[index] = updateStationDetail; // Update the manager station in the state
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addCase(updateStationDetails.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload || "Failed to update manager";
|
||||||
|
})
|
||||||
|
|
||||||
|
// Delete Manager
|
||||||
|
.addCase(deleteStationDetails.pending, (state) => {
|
||||||
|
state.loading = true;
|
||||||
|
})
|
||||||
|
.addCase(deleteStationDetails.fulfilled, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.stationDetails = state.stationDetails.filter(
|
||||||
|
(stationDetail) =>
|
||||||
|
String(stationDetail.id) !== String(action.payload)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.addCase(deleteStationDetails.rejected, (state, action) => {
|
||||||
|
state.loading = false;
|
||||||
|
state.error = action.payload || "Failed to delete manager";
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default managerStationSlice.reducer;
|
|
@ -28,6 +28,9 @@ const ExternalStationList = lazy(
|
||||||
);
|
);
|
||||||
const AllManagersList = lazy(() => import("./pages/AllMangersList"));
|
const AllManagersList = lazy(() => import("./pages/AllMangersList"));
|
||||||
const AvailableSlotsList = lazy(() => import("./pages/AvailableSlotsList"));
|
const AvailableSlotsList = lazy(() => import("./pages/AvailableSlotsList"));
|
||||||
|
const ManagerStationDetails = lazy(
|
||||||
|
() => import("./pages/ManagerStationDetails")
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
interface ProtectedRouteProps {
|
interface ProtectedRouteProps {
|
||||||
|
@ -136,7 +139,14 @@ export default function AppRouter() {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="manager-station-details"
|
||||||
|
element={
|
||||||
|
<ProtectedRoute
|
||||||
|
component={<ManagerStationDetails />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
{/* Catch-all Route */}
|
{/* Catch-all Route */}
|
||||||
|
|
|
@ -40,6 +40,7 @@ export const dataDisplayCustomizations = {
|
||||||
'&.Mui-selected': {
|
'&.Mui-selected': {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
backgroundColor: alpha(theme.palette.action.selected, 0.3),
|
backgroundColor: alpha(theme.palette.action.selected, 0.3),
|
||||||
|
|
||||||
[`& .${svgIconClasses.root}`]: {
|
[`& .${svgIconClasses.root}`]: {
|
||||||
color: (theme.vars || theme).palette.text.primary,
|
color: (theme.vars || theme).palette.text.primary,
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,6 +39,7 @@ export const dataDisplayCustomizations: Components<Theme> = {
|
||||||
'&.Mui-selected': {
|
'&.Mui-selected': {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
backgroundColor: alpha(theme.palette.action.selected, 0.3),
|
backgroundColor: alpha(theme.palette.action.selected, 0.3),
|
||||||
|
|
||||||
[`& .${svgIconClasses.root}`]: {
|
[`& .${svgIconClasses.root}`]: {
|
||||||
color: (theme.vars || theme).palette.text.primary,
|
color: (theme.vars || theme).palette.text.primary,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue