From 0f33303a4287ce20f16c7afae54378a3df2564da Mon Sep 17 00:00:00 2001 From: jaanvi Date: Thu, 27 Mar 2025 18:39:38 +0530 Subject: [PATCH 1/2] made changes in Charging Station and slots booking modals --- src/components/AddBookingModal/index.tsx | 12 +- src/components/AddManagerModal/index.tsx | 21 +- src/components/AddStationModal/index.tsx | 87 ++--- src/components/AddVehicleModal/index.tsx | 61 ++-- src/components/CustomTable/index.tsx | 324 +++++++++--------- src/components/EditManagerModal/index.tsx | 4 +- src/components/EditSlotModal/index.tsx | 12 +- src/components/EditStationModal/index.tsx | 277 ++++++++++----- src/components/Header/index.tsx | 16 +- src/components/MenuContent/index.tsx | 10 +- .../Modals/ViewManagerModal/index.tsx | 8 +- src/layouts/DashboardLayout/index.tsx | 4 - src/lib/https.ts | 30 +- src/pages/EvSlotList/index.tsx | 6 +- src/pages/StationList/index.tsx | 17 +- src/redux/slices/VehicleSlice.ts | 14 +- src/redux/slices/bookSlice.ts | 45 ++- src/redux/slices/managerSlice.ts | 3 + src/redux/slices/slotSlice.ts | 11 +- src/redux/slices/stationSlice.ts | 79 ++++- 20 files changed, 633 insertions(+), 408 deletions(-) diff --git a/src/components/AddBookingModal/index.tsx b/src/components/AddBookingModal/index.tsx index 21fa1f8..06bfb82 100644 --- a/src/components/AddBookingModal/index.tsx +++ b/src/components/AddBookingModal/index.tsx @@ -26,7 +26,7 @@ import { CustomIconButton, CustomTextField, } from "../AddEditUserModel/styled.css.tsx"; -import { stationList } from "../../redux/slices/stationSlice.ts"; +import { getAllStations, stationList } from "../../redux/slices/stationSlice.ts"; import { fetchAvailableSlots } from "../../redux/slices/slotSlice.ts"; import dayjs from "dayjs"; @@ -56,7 +56,7 @@ export default function AddBookingModal({ console.log("first", availableSlots); useEffect(() => { dispatch(fetchAvailableSlots()); - dispatch(stationList()); + dispatch(getAllStations()); }, [dispatch]); useEffect(() => { @@ -74,7 +74,7 @@ export default function AddBookingModal({ // Fetch the bookings after this dispatch(bookingList()); }, [dispatch]); - +console.log("Car Ports: ", carPorts); // Get today's date in yyyy-mm-dd format const today = new Date().toISOString().split("T")[0]; @@ -266,9 +266,9 @@ export default function AddBookingModal({ {carPorts.map((port, index) => ( - {port.chargeType} + {port} ))} @@ -290,7 +290,6 @@ export default function AddBookingModal({ {/* Start Time and End Time */} - Start Time @@ -311,7 +310,6 @@ export default function AddBookingModal({ /> - End Time diff --git a/src/components/AddManagerModal/index.tsx b/src/components/AddManagerModal/index.tsx index 23f9fb4..41f745c 100644 --- a/src/components/AddManagerModal/index.tsx +++ b/src/components/AddManagerModal/index.tsx @@ -172,14 +172,21 @@ useEffect(() => { defaultValue="" size="small" > - {stations.map((station) => ( - - {station.name} + {Array.isArray(stations) && + stations.length > 0 ? ( + stations.map((station) => ( + + {station.name} + + )) + ) : ( + + No stations available - ))} + )} {errors.stationName && ( diff --git a/src/components/AddStationModal/index.tsx b/src/components/AddStationModal/index.tsx index ff7ba74..f73b639 100644 --- a/src/components/AddStationModal/index.tsx +++ b/src/components/AddStationModal/index.tsx @@ -46,58 +46,59 @@ export default function AddStationModal({ const vehicleBrands = useSelector( (state: RootState) => state.vehicleReducer.vehicleBrands ); - const [selectedBrand, setSelectedBrand] = useState(""); - - useEffect(() => { - dispatch(fetchVehicleBrands()); - dispatch(vehicleList()); // Fetch vehicles when the component mounts - }, [dispatch]); - const filteredVehicles = vehicles.filter( - (vehicle) => vehicle.company === selectedBrand - ); + // State for selected vehicle brand and vehicles + const [selectedBrands, setSelectedBrands] = useState([]); const [selectedVehicles, setSelectedVehicles] = useState([]); - // Handle the change in selected vehicles (checkboxes) - const handleCheckboxChange = ( + // Fetch vehicle brands and vehicle list when the component mounts + useEffect(() => { + dispatch(fetchVehicleBrands()); + dispatch(vehicleList()); + }, [dispatch]); + + // Filter vehicles based on selected vehicle brands + const filteredVehicles = vehicles.filter((vehicle) => + selectedBrands.includes(vehicle.company) + ); + + // Handle changes in selected vehicle brands (checkboxes) + const handleBrandChange = ( event: React.ChangeEvent<{ value: unknown }> ) => { const value = event.target.value as string[]; - setSelectedVehicles(value); + setSelectedBrands(value); // Update the selected vehicle brands + }; + + // Handle changes in selected vehicles (checkboxes) + const handleVehicleChange = ( + event: React.ChangeEvent<{ value: unknown }> + ) => { + setSelectedVehicles(event.target.value as string[]); }; // Function to map selected vehicle names to corresponding vehicle ids const getVehicleIds = () => { - console.log("Selected Vehicles: ", selectedVehicles); - console.log("Vehicles List: ", vehicles); return vehicles .filter((vehicle) => selectedVehicles.includes(vehicle.name)) .map((vehicle) => vehicle.id); }; const onSubmit = (data: any) => { - // Log the data before sending to backend - console.log("Payload being sent to hfgghfhbackend:", data); - const vehicleIds = getVehicleIds(); // Get the ids of the selected vehicles - console.log("Vehicle IDs: ", vehicleIds); - // Prepare the data to be sent to the backend const payload = { ...data, - status: 1, // Default status, can be adjusted if needed + status: 1, // Default status allowedCarIds: vehicleIds, // Pass the vehicle ids to the backend totalSlots: Number(data.totalSlots), // Ensure this is a number }; - console.log("Payload to backend:", payload); // Log the final payload - - // Handle adding the station with the constructed payload handleAddStation(payload); handleClose(); // Close modal after adding reset(); setSelectedVehicles([]); - setSelectedBrand(""); // Reset selected vehicles after submission + setSelectedBrands([]); // Reset selected brands after submission }; return ( @@ -251,7 +252,7 @@ export default function AddStationModal({ - {/* Vehicle Name Dropdown with Checkboxes */} + {/* Vehicle Brand Dropdown with Checkboxes */} - Select Vehicle Brand + Select Vehicle Brands - Choose Brand + Choose Brands diff --git a/src/components/AddVehicleModal/index.tsx b/src/components/AddVehicleModal/index.tsx index 1707720..3334d40 100644 --- a/src/components/AddVehicleModal/index.tsx +++ b/src/components/AddVehicleModal/index.tsx @@ -83,6 +83,36 @@ export default function AddVehicleModal({ > {/* First Row - Two Inputs */} + + + Company Name + + + - - - - Company - - - {/* Second Row - Two Inputs */} diff --git a/src/components/CustomTable/index.tsx b/src/components/CustomTable/index.tsx index 2337733..7db5231 100644 --- a/src/components/CustomTable/index.tsx +++ b/src/components/CustomTable/index.tsx @@ -40,7 +40,7 @@ import { deleteSlot, fetchAvailableSlots, } from "../../redux/slices/slotSlice.ts"; -import { bookingList } from "../../redux/slices/bookSlice.ts"; +import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts"; // Styled components for customization const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { @@ -155,6 +155,9 @@ const CustomTable: React.FC = ({ case "slots": dispatch(deleteSlot(id || "")); break; + case "booking": + dispatch(deleteBooking(id || "")); + break; default: console.error("Unknown table type:", tableType); return; @@ -483,175 +486,174 @@ const CustomTable: React.FC = ({ /> {/* Menu Actions */} - {open && - ( - + + + {tableType === "role" && ( + - {viewModal && tableType === "admin" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "vehicle" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "manager" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "user" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "station" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} + {selectedRow?.statusValue === 1 + ? "Deactivate" + : "Activate"} + + )} + {tableType === "station" && ( + + )} - - {tableType === "role" && ( - - )} - {tableType === "station" && ( - - )} - - - - - )} + + + + )} {/* Modals */} {deleteModal && ( = ({ email: data.email, phone: data.phone, stationId: data.stationId, - Manager: undefined, - id: 0, - chargingStation: "" + }, }) ).unwrap(); // Ensure that it throws an error if the update fails diff --git a/src/components/EditSlotModal/index.tsx b/src/components/EditSlotModal/index.tsx index f1ad819..dbf581e 100644 --- a/src/components/EditSlotModal/index.tsx +++ b/src/components/EditSlotModal/index.tsx @@ -52,7 +52,7 @@ const EditSlotModal: React.FC = ({ const [loading, setLoading] = useState(false); const [isAvailable, setIsAvailable] = useState( editRow?.isAvailable || false - ); // Default to editRow availability + ); // Set values if editRow is provided useEffect(() => { @@ -68,6 +68,8 @@ const EditSlotModal: React.FC = ({ const onSubmit = async (data: FormData) => { if (editRow) { + setLoading(true); // Start loading + try { // Convert boolean availability to 1/0 const availabilityStatus = isAvailable ? true : false; @@ -83,12 +85,14 @@ const EditSlotModal: React.FC = ({ }, }) ).unwrap(); // Ensure that it throws an error if the update fails - dispatch(fetchAvailableSlots()); // Assuming this action fetches the updated slot list + + // Refresh the list after updating the slot + dispatch(fetchAvailableSlots()); handleClose(); // Close modal on success reset(); // Reset form fields after submit } catch (error) { - console.error(error); - // Handle the error or show a toast + console.error("Error updating slot:", error); + // Handle the error or show a toast message } finally { setLoading(false); // Stop loading state } diff --git a/src/components/EditStationModal/index.tsx b/src/components/EditStationModal/index.tsx index c6872ed..047e6ef 100644 --- a/src/components/EditStationModal/index.tsx +++ b/src/components/EditStationModal/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import { Box, Button, @@ -10,21 +10,27 @@ import { MenuItem, Checkbox, ListItemText, + FormHelperText, } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; import { useForm, Controller } from "react-hook-form"; +import { useSelector, useDispatch } from "react-redux"; +import { RootState } from "../../redux/reducers.ts"; +import { + fetchVehicleBrands, + vehicleList, +} from "../../redux/slices/VehicleSlice"; import { CustomIconButton, CustomTextField, -} from "../AddEditUserModel/styled.css.tsx"; +} from "../AddEditUserModel/styled.css.tsx"; // Assuming custom styled components -// Define the types for your form data interface FormData { name: string; registeredAddress: string; totalSlots: number; + allowedCarIds: string[]; status: number; - allowedCarIds: string[]; // Assuming allowedCarIds are the vehicle IDs } interface EditStationModalProps { @@ -35,10 +41,9 @@ interface EditStationModalProps { name: string, registeredAddress: string, totalSlots: number, - allowedCarIds: string[] + allowedCarIds: number[] ) => void; editRow?: any; - vehicles: { id: string; name: string }[]; } const EditStationModal: React.FC = ({ @@ -46,54 +51,82 @@ const EditStationModal: React.FC = ({ handleClose, handleUpdate, editRow, - vehicles, }) => { - const { control, handleSubmit, setValue, reset, watch } = useForm( - { - defaultValues: { - name: "", - registeredAddress: "", - totalSlots: 0, - status: 1, - allowedCarIds: [], - }, - } + const { + control, + handleSubmit, + setValue, + reset, + watch, + formState: { errors }, + } = useForm({ + defaultValues: { + name: "", + registeredAddress: "", + totalSlots: 0, + status: 1, + allowedCarIds: [], + }, + }); + + const dispatch = useDispatch(); + const vehicles = useSelector( + (state: RootState) => state.vehicleReducer.vehicles + ); + const vehicleBrands = useSelector( + (state: RootState) => state.vehicleReducer.vehicleBrands ); - // Watch allowedCarIds from the form state - const allowedCarIds = watch("allowedCarIds"); + const [selectedBrand, setSelectedBrand] = useState(""); + const [selectedVehicles, setSelectedVehicles] = useState([]); + + useEffect(() => { + dispatch(fetchVehicleBrands()); + dispatch(vehicleList()); // Fetch vehicles when the component mounts + }, [dispatch]); - // Set values when editRow is provided useEffect(() => { if (editRow) { setValue("name", editRow.name); setValue("registeredAddress", editRow.registeredAddress); setValue("totalSlots", editRow.totalSlots); setValue("status", editRow.status); - - // Set the allowedCarIds with the previously selected vehicle IDs - setValue( - "allowedCarIds", - editRow.allowedCarIds?.map((car: any) => car.id) || [] - ); + setValue("allowedCarIds", editRow.allowedCarIds || []); + setSelectedVehicles(editRow.allowedCarIds || []); } else { reset(); } }, [editRow, setValue, reset]); - // Handle form submit + + const filteredVehicles = vehicles.filter( + (vehicle) => vehicle.company === selectedBrand + ); + + const handleCheckboxChange = ( + event: React.ChangeEvent<{ value: unknown }> + ) => { + const value = event.target.value as string[]; + setSelectedVehicles(value); + setValue("allowedCarIds", value); // Update allowedCarIds in form state + }; + const onSubmit = (data: FormData) => { - if (editRow) { - handleUpdate( - editRow.id, - data.name, - data.registeredAddress, - data.totalSlots, - data.allowedCarIds - ); - } - handleClose(); // Close the modal after update - reset(); // Reset the form fields + const vehicleIds = vehicles + .filter((vehicle) => selectedVehicles.includes(vehicle.name)) + .map((vehicle) => vehicle.id); + + handleUpdate( + editRow.id, + data.name, + data.registeredAddress, + data.totalSlots, + vehicleIds + ); + handleClose(); + reset(); + setSelectedBrand(""); // Reset brand after submit + setSelectedVehicles([]); // Reset selected vehicles }; return ( @@ -103,7 +136,7 @@ const EditStationModal: React.FC = ({ if (reason === "backdropClick") { return; } - handleClose(); // Close modal when clicking cross or cancel + handleClose(); }} aria-labelledby="edit-station-modal" > @@ -141,9 +174,9 @@ const EditStationModal: React.FC = ({ {/* Horizontal Line */} - {/* Input Fields */} + {/* Form */} - {/* First Row - Two Inputs */} + {/* Station Name and Address */} = ({ fullWidth placeholder="Enter Station Name" size="small" + error={!!errors.name} + helperText={ + errors.name + ? errors.name.message + : "" + } /> )} /> - = ({ fullWidth placeholder="Enter Registered Address" size="small" + error={!!errors.registeredAddress} + helperText={ + errors.registeredAddress + ? errors.registeredAddress + .message + : "" + } /> )} /> - {/* Second Row - Total Slots */} + {/* Total Slots */} = ({ placeholder="Enter Total Slots" size="small" type="number" + error={!!errors.totalSlots} + helperText={ + errors.totalSlots + ? errors.totalSlots.message + : "" + } /> )} /> - {/* Vehicle Dropdown with Checkboxes */} - - - Vehicle Names - - - Choose Vehicles - - + {/* Vehicle Brand Selection */} + + + + Select Vehicle Brand + + + Choose Brand + + + + + {/* Vehicle Selection with Checkboxes */} + + + Vehicle Name + + + Choose Vehicles + + + {errors.allowedCarIds + ? errors.allowedCarIds.message + : ""} + + + @@ -300,7 +391,7 @@ const EditStationModal: React.FC = ({ "&:hover": { backgroundColor: "#439BC1" }, }} > - Update Charging Station + Update Station diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 83dca3c..80247c2 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -15,22 +15,21 @@ import { AppDispatch, RootState } from "../../redux/store/store"; import { fetchAdminProfile } from "../../redux/slices/profileSlice"; import OptionsMenu from "../OptionsMenu"; import NotificationsNoneIcon from "@mui/icons-material/NotificationsNone"; +import ColorModeIconDropdown from "../../shared-theme/ColorModeIconDropdown"; export default function Header() { const [showNotifications, setShowNotifications] = React.useState(false); const toggleNotifications = () => { setShowNotifications((prev) => !prev); }; - const [open, setOpen] = React.useState(true); + const [open, setOpen] = React.useState(true); - const dispatch = useDispatch(); - const { user } = useSelector( - (state: RootState) => state?.profileReducer - ); + const dispatch = useDispatch(); + const { user } = useSelector((state: RootState) => state?.profileReducer); - React.useEffect(() => { - dispatch(fetchAdminProfile()); - }, [dispatch]); + React.useEffect(() => { + dispatch(fetchAdminProfile()); + }, [dispatch]); return ( -