218 lines
5.5 KiB
TypeScript
218 lines
5.5 KiB
TypeScript
import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
|
|
import http from "../../lib/https";
|
|
import { toast } from "sonner";
|
|
|
|
// Define the structure for carDetails
|
|
interface CarDetails {
|
|
name: string;
|
|
number: string;
|
|
model: string;
|
|
}
|
|
|
|
interface Booking {
|
|
id: number;
|
|
slotId: number;
|
|
stationId: string;
|
|
stationName: string;
|
|
stationLocation: string;
|
|
date: string;
|
|
startTime: string;
|
|
endTime: string;
|
|
carDetails: CarDetails;
|
|
carNames: string[]; // For car names
|
|
carPorts: string[]; // For car ports
|
|
}
|
|
|
|
interface BookingState {
|
|
bookings: Booking[];
|
|
loading: boolean;
|
|
error: string | null;
|
|
carNames: string[]; // For car names
|
|
carPorts: string[]; // For car ports
|
|
}
|
|
|
|
const initialState: BookingState = {
|
|
bookings: [],
|
|
loading: false,
|
|
error: null,
|
|
carNames: [], // Initialize carNames
|
|
carPorts: [], // Initialize carPorts
|
|
};
|
|
|
|
// Redux slice for fetching car names and ports
|
|
export const getCarNames = createAsyncThunk<
|
|
string[],
|
|
void,
|
|
{ rejectValue: string }
|
|
>("fetchCarNames", async (_, { rejectWithValue }) => {
|
|
try {
|
|
const response = await http.get("/get-vehicle-dropdown");
|
|
return response.data.data; // Adjust based on actual API response
|
|
} catch (error: any) {
|
|
return rejectWithValue(
|
|
error?.response?.data?.message || "An error occurred"
|
|
);
|
|
}
|
|
});
|
|
|
|
export const getCarPorts = createAsyncThunk<
|
|
string[],
|
|
void,
|
|
{ rejectValue: string }
|
|
>("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(
|
|
error?.response?.data?.message || "An error occurred"
|
|
);
|
|
}
|
|
});
|
|
|
|
// Fetch booking list
|
|
export const bookingList = createAsyncThunk<
|
|
Booking[],
|
|
void,
|
|
{ rejectValue: string }
|
|
>("fetchBooking", async (_, { rejectWithValue }) => {
|
|
try {
|
|
const token = localStorage?.getItem("authToken");
|
|
if (!token) throw new Error("No token found");
|
|
|
|
const response = await http.get("/user-bookings");
|
|
console.log("API Response:", response);
|
|
|
|
if (!response.data?.data) throw new Error("Invalid API response");
|
|
|
|
return response.data.data; // Updated to access data
|
|
} catch (error: any) {
|
|
toast.error("Error Fetching User Booking List: " + error.message);
|
|
return rejectWithValue(
|
|
error?.response?.data?.message || "An error occurred"
|
|
);
|
|
}
|
|
});
|
|
|
|
// Add a new booking
|
|
export const addBooking = createAsyncThunk<
|
|
Booking,
|
|
{
|
|
stationId: string;
|
|
date: string;
|
|
startTime: string;
|
|
endTime: string;
|
|
carName: string;
|
|
carNumber: string;
|
|
carPort: string;
|
|
},
|
|
{ rejectValue: string }
|
|
>("/AddBooking", async (data, { rejectWithValue }) => {
|
|
try {
|
|
const response = await http.post("/book-slot", data);
|
|
toast.success("EV Booked Successfully!");
|
|
return response.data.data; // Adjust to match the new API response structure
|
|
} catch (error: any) {
|
|
toast.error(
|
|
"The requested time slot doesn't fall within any available slot "
|
|
);
|
|
return rejectWithValue(
|
|
error.response?.data?.message || "An error occurred"
|
|
);
|
|
}
|
|
});
|
|
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,
|
|
reducers: {},
|
|
extraReducers: (builder) => {
|
|
builder
|
|
.addCase(bookingList.pending, (state) => {
|
|
state.loading = true;
|
|
state.error = null;
|
|
})
|
|
.addCase(
|
|
bookingList.fulfilled,
|
|
(state, action: PayloadAction<Booking[]>) => {
|
|
state.loading = false;
|
|
state.bookings = action.payload;
|
|
}
|
|
)
|
|
.addCase(bookingList.rejected, (state, action) => {
|
|
state.loading = false;
|
|
state.error =
|
|
action.error.message || "Failed to fetch bookings";
|
|
})
|
|
.addCase(addBooking.pending, (state) => {
|
|
state.loading = true;
|
|
})
|
|
.addCase(
|
|
addBooking.fulfilled,
|
|
(state, action: PayloadAction<Booking>) => {
|
|
state.loading = false;
|
|
state.bookings.push(action.payload); // Add new booking to state
|
|
}
|
|
)
|
|
.addCase(addBooking.rejected, (state) => {
|
|
state.loading = false;
|
|
})
|
|
// Add case reducers for fetching car names and ports
|
|
.addCase(
|
|
getCarNames.fulfilled,
|
|
(state, action: PayloadAction<string[]>) => {
|
|
state.carNames = action.payload;
|
|
}
|
|
)
|
|
.addCase(
|
|
getCarPorts.fulfilled,
|
|
(state, action: PayloadAction<string[]>) => {
|
|
state.carPorts = action.payload;
|
|
}
|
|
)
|
|
.addCase(deleteBooking.pending, (state) => {
|
|
state.loading = true;
|
|
})
|
|
.addCase(
|
|
deleteBooking.fulfilled,
|
|
(state, action: PayloadAction<string>) => {
|
|
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";
|
|
});
|
|
},
|
|
});
|
|
|
|
export default bookSlice.reducer;
|