diff --git a/src/components/AddBookingModal/index.tsx b/src/components/AddBookingModal/index.tsx index 7dee154..c28f93a 100644 --- a/src/components/AddBookingModal/index.tsx +++ b/src/components/AddBookingModal/index.tsx @@ -1,3 +1,4 @@ +import React, { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { Box, @@ -5,13 +6,22 @@ import { Typography, Modal, IconButton, - InputAdornment, + MenuItem, + Select, + InputLabel, + FormControl, + TextField, } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; -import { Visibility, VisibilityOff } from "@mui/icons-material"; import { useDispatch } from "react-redux"; -import { addBooking, bookingList } from "../../redux/slices/bookSlice.ts"; -import React, { useState } from "react"; +import { + addBooking, + bookingList, + getCarNames, + getCarPorts, +} from "../../redux/slices/bookSlice"; +import { AppDispatch } from "../../redux/store/store"; +import { toast } from "sonner"; import { CustomIconButton, CustomTextField, @@ -24,19 +34,35 @@ export default function AddBookingModal({ open: boolean; handleClose: () => void; }) { - const dispatch = useDispatch(); + const dispatch = useDispatch(); const { control, register, handleSubmit, formState: { errors }, reset, - watch, } = useForm(); + const [carNames, setCarNames] = useState([]); // To hold the car names + const [carPorts, setCarPorts] = useState([]); // To hold the car ports - const [showPassword, setShowPassword] = useState(false); + useEffect(() => { + // Fetch car names and car ports + dispatch(getCarNames()).then((response: any) => { + const fetchedCarNames = response.payload || []; + setCarNames(fetchedCarNames); + }); - const togglePasswordVisibility = () => setShowPassword((prev) => !prev); + dispatch(getCarPorts()).then((response: any) => { + const fetchedCarPorts = response.payload || []; + setCarPorts(fetchedCarPorts); + }); + + // Fetch the bookings after this + dispatch(bookingList()); + }, [dispatch]); + + // Get today's date in yyyy-mm-dd format + const today = new Date().toISOString().split("T")[0]; const onSubmit = async (data: any) => { const bookingData = { @@ -44,6 +70,9 @@ export default function AddBookingModal({ date: data.date, startTime: data.startTime, endTime: data.endTime, + carName: data.carName, + carNumber: data.carNumber, + carPort: data.carPort, }; try { @@ -53,6 +82,7 @@ export default function AddBookingModal({ reset(); // Reset form fields } catch (error) { console.error("Error adding booking:", error); + toast.error("Failed to add booking."); } }; @@ -60,9 +90,7 @@ export default function AddBookingModal({ { - if (reason === "backdropClick") { - return; - } + if (reason === "backdropClick") return; handleClose(); }} aria-labelledby="add-booking-modal" @@ -80,7 +108,6 @@ export default function AddBookingModal({ borderRadius: 2, }} > - {/* Header */}
- {/* Station ID Input */} + {/* Station ID and Car Name */} + {/* Station ID */} Station ID @@ -119,41 +147,134 @@ export default function AddBookingModal({ })} /> - - - {/* Date Input */} - Date + value >= today || + "Date cannot be in the past", })} + InputLabelProps={{ + shrink: true, + }} + // Setting minimum date to today + inputProps={{ min: today }} /> - {/* Start Time Input */} + {/* Car Port and Date */} + {/* Car Name */} + + + Car Name + + ( + + Car Name + + {errors.carName && ( + + {errors.carName.message} + + )} + + )} + rules={{ required: "Car Name is required" }} + /> + + {/* Car Port */} + + + Car Port + + ( + + Car Port + + {errors.carPort && ( + + {errors.carPort.message} + + )} + + )} + rules={{ required: "Car Port is required" }} + /> + + + + {/* Start Time and End Time */} + + {/* Start Time */} Start Time - - {/* End Time Input */} - + {/* End Time */} End Time { - const startTime = watch("startTime"); - if (value <= startTime) { - return "End time must be after start time."; - } - return true; - }, + })} + /> + + + + {/* Car Number */} + + + + Car Number + + @@ -201,7 +335,7 @@ export default function AddBookingModal({ sx={{ display: "flex", justifyContent: "flex-end", - mt: 3, + mt: 2, }} > + + {isAvailable ? "Available" : "Not Available"} + + + + + + - - {error && ( - - {error} - - )} - - - {/* Break Time */} - - Break Time - - - - - - - - {/* Slots and Break Times Lists */} - {/* (Content for slots and breaks remains the same as in the original implementation) */} - - {/* Success Snackbar */} - + width: "100px", + "&:hover": { backgroundColor: "#439BC1" }, + }} + > + Add Booking + + + +
- - - - - ); -} - +}; +export default AddSlotModal; diff --git a/src/components/CustomTable/index.tsx b/src/components/CustomTable/index.tsx index 59def27..2090518 100644 --- a/src/components/CustomTable/index.tsx +++ b/src/components/CustomTable/index.tsx @@ -11,7 +11,7 @@ import { adminList, deleteAdmin } from "../../redux/slices/adminSlice"; import { vehicleList, deleteVehicle } from "../../redux/slices/VehicleSlice"; import { deleteManager, managerList } from "../../redux/slices/managerSlice"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { Box, Button, @@ -24,7 +24,7 @@ import { } from "@mui/material"; import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded"; import DeleteModal from "../Modals/DeleteModal"; -import { AppDispatch } from "../../redux/store/store"; +import { AppDispatch, RootState } from "../../redux/store/store"; import ViewModal from "../Modals/ViewModal"; import VehicleViewModal from "../Modals/VehicleViewModal"; @@ -36,7 +36,10 @@ import UserViewModal from "../Modals/UserViewModal/index.tsx"; import { deleteUser, userList } from "../../redux/slices/userSlice.ts"; import { deleteStation } from "../../redux/slices/stationSlice.ts"; import StationViewModal from "../Modals/StationViewModal/index.tsx"; -import { fetchAvailableSlots } from "../../redux/slices/slotSlice.ts"; +import { + deleteSlot, + fetchAvailableSlots, +} from "../../redux/slices/slotSlice.ts"; import { bookingList } from "../../redux/slices/bookSlice.ts"; // Styled components for customization const StyledTableCell = styled(TableCell)(({ theme }) => ({ @@ -105,14 +108,17 @@ const CustomTable: React.FC = ({ const [searchQuery, setSearchQuery] = React.useState(""); const [currentPage, setCurrentPage] = React.useState(1); const usersPerPage = 10; - + const { user, isLoading } = useSelector( + (state: RootState) => state?.profileReducer + ); const open = Boolean(anchorEl); - + console.log("Rows", rows); const handleClick = (event: React.MouseEvent, row: Row) => { setAnchorEl(event.currentTarget); setSelectedRow(row); setRowData(row); }; + const handleClose = () => { setAnchorEl(null); }; @@ -125,9 +131,13 @@ const CustomTable: React.FC = ({ }; const handleDeleteButton = (id: string | undefined) => { - if (!id) console.error("ID not found", id); + if (!id) { + console.error("ID not found", id); + return; + } switch (tableType) { + case "admin": dispatch(deleteAdmin(id || "")); break; @@ -143,9 +153,9 @@ const CustomTable: React.FC = ({ case "station": dispatch(deleteStation(id || "")); break; - // case "booking": - // dispatch(deleteBooking(id || "")); - // break; + case "slots": + dispatch(deleteSlot(id || "")); + break; default: console.error("Unknown table type:", tableType); return; @@ -172,6 +182,9 @@ const CustomTable: React.FC = ({ case "booking": dispatch(bookingList()); break; + case "slots": + dispatch(fetchAvailableSlots()); + break; default: console.error("Unknown table type:", tableType); return; @@ -240,6 +253,8 @@ const CustomTable: React.FC = ({ ? "Charging Station" : tableType === "booking" ? "Booking" + : tableType === "slots" + ? "Slot" : "List"} @@ -290,33 +305,37 @@ const CustomTable: React.FC = ({ width: "100%", }} > - + {!(user?.userType === "user" && tableType === "slots") && ( + + )}