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) => (
))}
@@ -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) => (
-
- {/* Vehicle Name Dropdown with Checkboxes */}
+ {/* Vehicle Brand Dropdown with Checkboxes */}
- Select Vehicle Brand
+ Select Vehicle Brands
- Choose Brand
+ Choose Brands
+
- {/* Vehicle Name Dropdown with Checkboxes */}
+
(selected as string[]).join(", ")
}
@@ -337,8 +346,8 @@ export default function AddStationModal({
))
) : (
- No vehicles available for this
- brand
+ No vehicles available for the
+ selected 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 &&
- (
-
- )}
+
+
+
+ )}
{/* 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 (
-
,
- // url: "/panel/EVslots", // Placeholder for now
+ // text: "Add Slots",
+ // icon: ,
+ // url: "/panel/EVslots", // Placeholder for now
// },
userRole === "user" && {
text: "Bookings",
@@ -103,13 +103,13 @@ export default function MenuContent({ hidden }: PropType) {
state.managerReducer
);
const [selectedManager, setSelectedManager] = useState(null);
-
+
useEffect(() => {
if (id) {
@@ -110,7 +110,8 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
Station Location:
- {selectedManager.registeredAddress}
+ {selectedManager.chargingStation
+ ?.registeredAddress || "Not Available"}
@@ -118,7 +119,8 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
Station Name:
- {selectedManager.stationName}
+ {selectedManager.chargingStation?.name ||
+ "Not Available"}
diff --git a/src/layouts/DashboardLayout/index.tsx b/src/layouts/DashboardLayout/index.tsx
index 6cb37b1..eb1ca8e 100644
--- a/src/layouts/DashboardLayout/index.tsx
+++ b/src/layouts/DashboardLayout/index.tsx
@@ -50,12 +50,8 @@ const DashboardLayout: React.FC = ({ customStyles }) => {
...customStyles,
mt: { xs: 8, md: 0 },
padding: 0,
-
})}
>
-
-
-
{
const authToken = localStorage.getItem("authToken");
if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`;
}
-
return config;
});
+
http.interceptors.response.use(
- (response) => response,
+ (response) => response,
(error) => {
-
- if (error.response && error.response.status === 403 ) {
- window.location.href = "/login";
-
- // const history = useHistory();
- // history.push("/login");
+ if (error.response) {
+ const status = error.response.status;
+ const requestUrl = error.config.url; // Get the API route
+
+ // Handle token expiration (401) but NOT for login failures
+ if (status === 401 && !requestUrl.includes("/login")) {
+ localStorage.removeItem("authToken");
+ window.location.href = "/login";
+ }
+
+ // Handle forbidden access
+ if (status === 403) {
+ localStorage.removeItem("authToken");
+ window.location.href = "/login";
+ }
}
- return Promise.reject(error);
+ return Promise.reject(error);
}
);
diff --git a/src/pages/EvSlotList/index.tsx b/src/pages/EvSlotList/index.tsx
index 4e8e0c7..4e34ad8 100644
--- a/src/pages/EvSlotList/index.tsx
+++ b/src/pages/EvSlotList/index.tsx
@@ -56,10 +56,10 @@ export default function EVSlotList() {
console.error("Error adding slot", error);
}
};
- console.log("isAvailable type:", typeof isAvailable);
+
const handleUpdate = async (
id: string,
- date: string,
+
startTime: string,
endTime: string,
isAvailable: boolean
@@ -69,7 +69,7 @@ export default function EVSlotList() {
await dispatch(
updateSlot({
id,
- date,
+
startTime,
endTime,
isAvailable,
diff --git a/src/pages/StationList/index.tsx b/src/pages/StationList/index.tsx
index fc0d6a0..549b10c 100644
--- a/src/pages/StationList/index.tsx
+++ b/src/pages/StationList/index.tsx
@@ -47,7 +47,8 @@ export default function StationList() {
const handleAddStation = async (data: {
name: string;
registeredAddress: string;
- totalSlots: string;
+ totalSlots: number;
+ allowedCarIds: number[];
}) => {
try {
await dispatch(createStation(data)); // Dispatch action to add Station
@@ -62,7 +63,7 @@ export default function StationList() {
id: string,
name: string,
registeredAddress: string,
- totalSlots: string,
+ totalSlots: number,
allowedCarIds: number[]
) => {
try {
@@ -88,9 +89,14 @@ export default function StationList() {
await dispatch(toggleStatus({ id, status: newStatus }));
};
- const filterStations = stations?.filter((station) =>
- station.name.toLocaleLowerCase().includes(searchTerm.toLowerCase())
- );
+ const filterStations = Array.isArray(stations)
+ ? stations.filter((station) =>
+ station.name
+ .toLocaleLowerCase()
+ .includes(searchTerm.toLowerCase())
+ )
+ : [];
+
// Mapping and formatting vehicles
const categoryRows = filterStations?.length
@@ -122,6 +128,7 @@ export default function StationList() {
};
})
: [];
+ console.log("Rowssss",categoryRows)
const categoryColumns: Column[] = [
{ id: "srno", label: "Sr No" },
diff --git a/src/redux/slices/VehicleSlice.ts b/src/redux/slices/VehicleSlice.ts
index ba71ebb..31cefed 100644
--- a/src/redux/slices/VehicleSlice.ts
+++ b/src/redux/slices/VehicleSlice.ts
@@ -2,6 +2,7 @@ import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import http from "../../lib/https";
import { toast } from "sonner";
interface VehicleBrand {
+ name: string;
id: string;
company: string;
}
@@ -34,19 +35,23 @@ export const fetchVehicleBrands = createAsyncThunk<
>("vehicle/fetchVehicleBrands", async (_, { rejectWithValue }) => {
try {
const response = await http.get("/get-vehicle-brand");
+
if (!response.data || !Array.isArray(response.data.data)) {
throw new Error("Expected array of vehicle brands");
}
- // Assuming that 'data' contains an array of objects with a 'company' field
- return response.data.data.map((item: any) => ({
- id: item.company, // You can use 'company' as the unique identifier
- name: item.company, // The name field will be used in the dropdown
+
+ // Map the brand names (strings) to objects with 'id' and 'name' properties
+ return response.data.data.map((brand: string) => ({
+ id: brand, // Use brand name as the ID
+ name: brand, // Use brand name as the label
}));
} catch (error: any) {
return rejectWithValue("Failed to fetch vehicle brands");
}
});
+
+
export const vehicleList = createAsyncThunk<
Vehicle,
void,
@@ -158,6 +163,7 @@ const vehicleSlice = createSlice({
state.vehicleBrands = action.payload;
}
)
+
.addCase(fetchVehicleBrands.rejected, (state, action) => {
state.loading = false;
state.error =
diff --git a/src/redux/slices/bookSlice.ts b/src/redux/slices/bookSlice.ts
index b96e81c..33335aa 100644
--- a/src/redux/slices/bookSlice.ts
+++ b/src/redux/slices/bookSlice.ts
@@ -60,6 +60,7 @@ export const getCarPorts = createAsyncThunk<
>("fetchCarPorts", async (_, { rejectWithValue }) => {
try {
const response = await http.get("/get-vehicle-port-dropdown");
+
return response.data.data; // Adjust based on actual API response
} catch (error: any) {
return rejectWithValue(
@@ -119,7 +120,22 @@ export const addBooking = createAsyncThunk<
);
}
});
-
+export const deleteBooking = createAsyncThunk<
+ string, // Return type (id of deleted slot)
+ string,
+ { rejectValue: string }
+>("booking/deleteBooking", async (id, { rejectWithValue }) => {
+ try {
+ const response = await http.delete(`/delete-booking/${id}`);
+ toast.success("Slot deleted successfully");
+ return id; // Return the id of the deleted slot
+ } catch (error: any) {
+ toast.error("Error deleting the slot: " + error?.message);
+ return rejectWithValue(
+ error.response?.data?.message || "An error occurred"
+ );
+ }
+});
const bookSlice = createSlice({
name: "booking",
initialState,
@@ -167,7 +183,32 @@ const bookSlice = createSlice({
(state, action: PayloadAction) => {
state.carPorts = action.payload;
}
- );
+ )
+ .addCase(deleteBooking.pending, (state) => {
+ state.loading = true;
+ })
+ .addCase(
+ deleteBooking.fulfilled,
+ (state, action: PayloadAction) => {
+ state.loading = false;
+ // Ensure we're filtering the correct array (bookings)
+ state.bookings = state.bookings.filter(
+ (booking) =>
+ String(booking.id) !== String(action.payload)
+ );
+ // Also update slots array if it exists
+ if (state.bookings) {
+ state.bookings = state.bookings.filter(
+ (booking) =>
+ String(booking.id) !== String(action.payload)
+ );
+ }
+ }
+ )
+ .addCase(deleteBooking.rejected, (state, action) => {
+ state.loading = false;
+ state.error = action.payload || "Failed to delete slot";
+ });
},
});
diff --git a/src/redux/slices/managerSlice.ts b/src/redux/slices/managerSlice.ts
index 410c1c9..e81282c 100644
--- a/src/redux/slices/managerSlice.ts
+++ b/src/redux/slices/managerSlice.ts
@@ -175,6 +175,9 @@ const managerSlice = createSlice({
})
.addCase(deleteManager.fulfilled, (state, action) => {
state.loading = false;
+ state.managers = state.managers.filter(
+ (manager) => String(manager.id) !== String(action.payload)
+ );
})
.addCase(deleteManager.rejected, (state, action) => {
state.loading = false;
diff --git a/src/redux/slices/slotSlice.ts b/src/redux/slices/slotSlice.ts
index 467d2ee..487d0ec 100644
--- a/src/redux/slices/slotSlice.ts
+++ b/src/redux/slices/slotSlice.ts
@@ -5,7 +5,7 @@ import { toast } from "sonner";
// Define TypeScript types
interface Slot {
id: string;
- stationId:string;
+ stationId: string;
date: string;
startTime: string;
endTime: string;
@@ -88,7 +88,7 @@ export const createSlot = createAsyncThunk<
// Update Slot details
export const updateSlot = createAsyncThunk<
Slot,
- { id: number; startTime: string; endTime: string }, // Argument type (slot update data)
+ { id: string; startTime: string; endTime: string }, // Argument type (slot update data)
{ rejectValue: string }
>("slots/updateSlot", async ({ id, ...slotData }, { rejectWithValue }) => {
try {
@@ -97,6 +97,7 @@ export const updateSlot = createAsyncThunk<
slotData
);
toast.success("Slot updated successfully");
+ console.log("Slots",response.data.data)
return response.data.data; // Return updated slot data
} catch (error: any) {
toast.error("Error updating the slot: " + error?.message);
@@ -104,7 +105,7 @@ export const updateSlot = createAsyncThunk<
error.response?.data?.message || "An error occurred"
);
}
-});
+});
export const deleteSlot = createAsyncThunk<
string, // Return type (id of deleted slot)
@@ -167,11 +168,11 @@ const slotSlice = createSlice({
(state, action: PayloadAction) => {
state.loading = false;
// Update the slot in the state with the updated data
- const index = state.slots.findIndex(
+ const index = state.availableSlots.findIndex(
(slot) => slot.id === action.payload.id
);
if (index !== -1) {
- state.slots[index] = action.payload;
+ state.availableSlots[index] = action.payload;
}
}
)
diff --git a/src/redux/slices/stationSlice.ts b/src/redux/slices/stationSlice.ts
index a6e4246..a9ead8a 100644
--- a/src/redux/slices/stationSlice.ts
+++ b/src/redux/slices/stationSlice.ts
@@ -8,7 +8,7 @@ interface Station {
id: string;
name: string;
registeredAddress: string;
- totalSlots: string;
+ totalSlots: number;
status: number;
allowedCarIds: number[];
}
@@ -47,14 +47,35 @@ export const stationList = createAsyncThunk(
}
}
);
+export const getAllStations = createAsyncThunk<
+ any,
+ void,
+ { rejectValue: string }
+>("getAllStations", async (_, { rejectWithValue }) => {
+ try {
+ const token = localStorage?.getItem("authToken");
+ if (!token) throw new Error("No token found");
+ const response = await http.get("/get-all-stations");
+
+ if (!response.data) throw new Error("Invalid API response");
+
+ // Return the full response to handle in the reducer
+ return response.data;
+ } catch (error: any) {
+ toast.error("Error Fetching Stations: " + error.message);
+ return rejectWithValue(
+ error?.response?.data?.message || "An error occurred"
+ );
+ }
+});
// Create Station
export const createStation = createAsyncThunk<
any,
{
name: string;
registeredAddress: string;
- totalSlots: string;
+ totalSlots: number;
allowedCarIds: number[];
},
{ rejectValue: string }
@@ -62,7 +83,7 @@ export const createStation = createAsyncThunk<
try {
const response = await http.post("/create-station", data);
toast.success("Station created successfully");
- return response.data;
+ return response.data; // Assuming the response contains the created station data
} catch (error: any) {
toast.error(
"Failed to create Station: " +
@@ -74,25 +95,31 @@ export const createStation = createAsyncThunk<
}
});
+// Update Station details
// Update Station details
export const updateStation = createAsyncThunk(
"updateStation",
async ({ id, ...stationData }: Station, { rejectWithValue }) => {
try {
+ // Exclude the `status` from the update payload
+ const { status, ...updateData } = stationData;
+
+ // Send the update request without the `status`
const response = await http.patch(
`/update-station/${id}`,
- stationData
+ updateData
);
- toast.success("Station Deatils updated successfully");
+ toast.success("Station Details updated successfully");
return response?.data;
} catch (error: any) {
- toast.error("Error updating the user: " + error);
+ toast.error("Error updating the station: " + error);
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
}
);
+
export const deleteStation = createAsyncThunk<
string,
string,
@@ -158,17 +185,30 @@ const stationSlice = createSlice({
stationList.fulfilled,
(state, action: PayloadAction) => {
state.loading = false;
- // Properly extract stations from the response data structure
- state.stations =
- action.payload.data?.results ||
- action.payload.data ||
- [];
+ // Correct data extraction
+ state.stations = action.payload.data?.stations || [];
}
)
.addCase(stationList.rejected, (state, action) => {
state.loading = false;
state.error = action.payload || "Failed to fetch stations";
})
+ .addCase(getAllStations.pending, (state) => {
+ state.loading = true;
+ state.error = null;
+ })
+ .addCase(
+ getAllStations.fulfilled,
+ (state, action: PayloadAction) => {
+ state.loading = false;
+ state.stations = action.payload.data || [];
+ }
+ )
+
+ .addCase(getAllStations.rejected, (state, action) => {
+ state.loading = false;
+ state.error = action.payload || "Failed to fetch stations";
+ })
.addCase(createStation.pending, (state) => {
state.loading = true;
})
@@ -176,12 +216,12 @@ const stationSlice = createSlice({
createStation.fulfilled,
(state, action: PayloadAction) => {
state.loading = false;
- // Add the newly created station to the state if it exists in the response
if (action.payload.data) {
state.stations.push(action.payload.data);
}
}
)
+
.addCase(
createStation.rejected,
(state, action: PayloadAction) => {
@@ -225,8 +265,21 @@ const stationSlice = createSlice({
})
.addCase(updateStation.fulfilled, (state, action) => {
state.loading = false;
- state.error = action.payload;
+ // If the station was updated, find and update it in the state
+ const updatedStation = action.payload;
+ const stationIndex = state.stations.findIndex(
+ (station) => station.id === updatedStation.id
+ );
+ if (stationIndex !== -1) {
+ // Here, merge the updated station with the existing one
+ // Ensure `status` is not overwritten if not explicitly updated
+ state.stations[stationIndex] = {
+ ...state.stations[stationIndex],
+ ...updatedStation,
+ };
+ }
})
+
.addCase(updateStation.rejected, (state) => {
state.loading = false;
})