dev-jaanvi #1

Open
jaanvi wants to merge 155 commits from dev-jaanvi into main
11 changed files with 7195 additions and 8290 deletions
Showing only changes of commit 87b971d97d - Show all commits

File diff suppressed because it is too large Load diff

View file

@ -26,7 +26,7 @@ import {
CustomIconButton, CustomIconButton,
CustomTextField, CustomTextField,
} from "../AddEditUserModel/styled.css.tsx"; } 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 { fetchAvailableSlots } from "../../redux/slices/slotSlice.ts";
import dayjs from "dayjs"; import dayjs from "dayjs";
@ -56,7 +56,7 @@ export default function AddBookingModal({
console.log("first", availableSlots); console.log("first", availableSlots);
useEffect(() => { useEffect(() => {
dispatch(fetchAvailableSlots()); dispatch(fetchAvailableSlots());
dispatch(stationList()); dispatch(getAllStations());
}, [dispatch]); }, [dispatch]);
useEffect(() => { useEffect(() => {
@ -74,7 +74,7 @@ export default function AddBookingModal({
// Fetch the bookings after this // Fetch the bookings after this
dispatch(bookingList()); dispatch(bookingList());
}, [dispatch]); }, [dispatch]);
console.log("Car Ports: ", carPorts);
// Get today's date in yyyy-mm-dd format // Get today's date in yyyy-mm-dd format
const today = new Date().toISOString().split("T")[0]; const today = new Date().toISOString().split("T")[0];
@ -266,9 +266,9 @@ export default function AddBookingModal({
{carPorts.map((port, index) => ( {carPorts.map((port, index) => (
<MenuItem <MenuItem
key={index} key={index}
value={port.chargeType} value={port}
> >
{port.chargeType} {port}
</MenuItem> </MenuItem>
))} ))}
</Select> </Select>
@ -290,7 +290,6 @@ export default function AddBookingModal({
{/* Start Time and End Time */} {/* Start Time and End Time */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}> <Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1 }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
Start Time Start Time
@ -311,7 +310,6 @@ export default function AddBookingModal({
/> />
</Box> </Box>
<Box sx={{ flex: 1 }}> <Box sx={{ flex: 1 }}>
<Typography variant="body2" fontWeight={500}> <Typography variant="body2" fontWeight={500}>
End Time End Time

View file

@ -42,9 +42,9 @@ export default function AddManagerModal({
(state: RootState) => state?.stationReducer.stations (state: RootState) => state?.stationReducer.stations
); );
useEffect(() => { useEffect(() => {
dispatch(stationList()); dispatch(stationList());
}, [dispatch]); }, [dispatch]);
// Handle form submission // Handle form submission
const onSubmit = async (data: any) => { const onSubmit = async (data: any) => {
@ -172,14 +172,21 @@ useEffect(() => {
defaultValue="" defaultValue=""
size="small" size="small"
> >
{stations.map((station) => ( {Array.isArray(stations) &&
stations.length > 0 ? (
stations.map((station) => (
<MenuItem <MenuItem
key={station.id} key={station.id}
value={station.name} value={station.name}
> >
{station.name} {station.name}
</MenuItem> </MenuItem>
))} ))
) : (
<MenuItem disabled>
No stations available
</MenuItem>
)}
</Select> </Select>
{errors.stationName && ( {errors.stationName && (
<Typography color="error" variant="body2"> <Typography color="error" variant="body2">

View file

@ -46,6 +46,8 @@ export default function AddStationModal({
const vehicleBrands = useSelector( const vehicleBrands = useSelector(
(state: RootState) => state.vehicleReducer.vehicleBrands (state: RootState) => state.vehicleReducer.vehicleBrands
); );
console.log("vehicle Brands", vehicleBrands);
const [selectedBrand, setSelectedBrand] = useState<string | "">(""); const [selectedBrand, setSelectedBrand] = useState<string | "">("");
useEffect(() => { useEffect(() => {
@ -86,7 +88,7 @@ export default function AddStationModal({
const payload = { const payload = {
...data, ...data,
status: 1, // Default status, can be adjusted if needed status: 1, // Default status, can be adjusted if needed
allowedCarIds: vehicleIds, // Pass the vehicle ids to the backend allowedCars: vehicleIds, // Pass the vehicle ids to the backend
totalSlots: Number(data.totalSlots), // Ensure this is a number totalSlots: Number(data.totalSlots), // Ensure this is a number
}; };

View file

@ -97,7 +97,7 @@ export default function Header() {
sx={{ width: 36, height: 36 }} sx={{ width: 36, height: 36 }}
/> />
<Typography variant="body1" sx={{ color: "#FFFFFF" }}> <Typography variant="body1" sx={{ color: "#FFFFFF" }}>
{user?.name || "No Admin"} {user?.name || "No Adminsss"}
</Typography> </Typography>
<OptionsMenu /> <OptionsMenu />

View file

@ -103,13 +103,13 @@ export default function MenuContent({ hidden }: PropType) {
<ListItem <ListItem
key={index} key={index}
disablePadding disablePadding
sx={{ display: "block", py: 1 }} sx={{ display: "block", py: 1, px: 0.9 }}
> >
<ListItemButton <ListItemButton
component={Link} component={Link}
to={item.url} to={item.url}
selected={item.url === location.pathname} selected={item.url === location.pathname}
sx={{ alignItems: "center", columnGap: 1 }} sx={{ alignItems: "center", columnGap: 0.5 }}
> >
<ListItemIcon <ListItemIcon
sx={{ sx={{

View file

@ -1,25 +1,35 @@
import axios from "axios"; import axios from "axios";
// import { useHistory } from "react-router-dom";
const http = axios.create({ const http = axios.create({
baseURL: process.env.REACT_APP_BACKEND_URL, baseURL: process.env.REACT_APP_BACKEND_URL,
}); });
http.interceptors.request.use((config) => { http.interceptors.request.use((config) => {
const authToken = localStorage.getItem("authToken"); const authToken = localStorage.getItem("authToken");
if (authToken) { if (authToken) {
config.headers.Authorization = `Bearer ${authToken}`; config.headers.Authorization = `Bearer ${authToken}`;
} }
return config; return config;
}); });
http.interceptors.response.use( http.interceptors.response.use(
(response) => response, (response) => response,
(error) => { (error) => {
if (error.response) {
const status = error.response.status;
const requestUrl = error.config.url; // Get the API route
if (error.response && error.response.status === 403 ) { // Handle token expiration (401) but NOT for login failures
if (status === 401 && !requestUrl.includes("/login")) {
localStorage.removeItem("authToken");
window.location.href = "/login"; window.location.href = "/login";
}
// const history = useHistory(); // Handle forbidden access
// history.push("/login"); if (status === 403) {
localStorage.removeItem("authToken");
window.location.href = "/login";
}
} }
return Promise.reject(error); return Promise.reject(error);
} }

View file

@ -88,9 +88,13 @@ export default function StationList() {
await dispatch(toggleStatus({ id, status: newStatus })); await dispatch(toggleStatus({ id, status: newStatus }));
}; };
const filterStations = stations?.filter((station) => const filterStations = Array.isArray(stations)
station.name.toLocaleLowerCase().includes(searchTerm.toLowerCase()) ? stations.filter((station) =>
); station.name
.toLocaleLowerCase()
.includes(searchTerm.toLowerCase())
)
: [];
// Mapping and formatting vehicles // Mapping and formatting vehicles
const categoryRows = filterStations?.length const categoryRows = filterStations?.length

View file

@ -37,11 +37,10 @@ export const fetchVehicleBrands = createAsyncThunk<
if (!response.data || !Array.isArray(response.data.data)) { if (!response.data || !Array.isArray(response.data.data)) {
throw new Error("Expected array of vehicle brands"); throw new Error("Expected array of vehicle brands");
} }
console.log("beans", response.data.data)
// Assuming that 'data' contains an array of objects with a 'company' field // Assuming that 'data' contains an array of objects with a 'company' field
return response.data.data.map((item: any) => ({ return response.data.data;
id: item.company, // You can use 'company' as the unique identifier
name: item.company, // The name field will be used in the dropdown
}));
} catch (error: any) { } catch (error: any) {
return rejectWithValue("Failed to fetch vehicle brands"); return rejectWithValue("Failed to fetch vehicle brands");
} }

View file

@ -60,7 +60,9 @@ export const getCarPorts = createAsyncThunk<
>("fetchCarPorts", async (_, { rejectWithValue }) => { >("fetchCarPorts", async (_, { rejectWithValue }) => {
try { try {
const response = await http.get("/get-vehicle-port-dropdown"); const response = await http.get("/get-vehicle-port-dropdown");
return response.data.data; // Adjust based on actual API response return response.data.data; // Adjust based on actual API response
} catch (error: any) { } catch (error: any) {
return rejectWithValue( return rejectWithValue(
error?.response?.data?.message || "An error occurred" error?.response?.data?.message || "An error occurred"

View file

@ -8,7 +8,7 @@ interface Station {
id: string; id: string;
name: string; name: string;
registeredAddress: string; registeredAddress: string;
totalSlots: string; totalSlots: number;
status: number; status: number;
allowedCarIds: number[]; allowedCarIds: number[];
} }
@ -47,14 +47,35 @@ export const stationList = createAsyncThunk<any, void, { rejectValue: string }>(
} }
} }
); );
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 // Create Station
export const createStation = createAsyncThunk< export const createStation = createAsyncThunk<
any, any,
{ {
name: string; name: string;
registeredAddress: string; registeredAddress: string;
totalSlots: string; totalSlots: number;
allowedCarIds: number[]; allowedCarIds: number[];
}, },
{ rejectValue: string } { rejectValue: string }
@ -62,7 +83,7 @@ export const createStation = createAsyncThunk<
try { try {
const response = await http.post("/create-station", data); const response = await http.post("/create-station", data);
toast.success("Station created successfully"); toast.success("Station created successfully");
return response.data; return response.data; // Assuming the response contains the created station data
} catch (error: any) { } catch (error: any) {
toast.error( toast.error(
"Failed to create Station: " + "Failed to create Station: " +
@ -74,25 +95,31 @@ export const createStation = createAsyncThunk<
} }
}); });
// Update Station details
// Update Station details // Update Station details
export const updateStation = createAsyncThunk( export const updateStation = createAsyncThunk(
"updateStation", "updateStation",
async ({ id, ...stationData }: Station, { rejectWithValue }) => { async ({ id, ...stationData }: Station, { rejectWithValue }) => {
try { try {
// Exclude the `status` from the update payload
const { status, ...updateData } = stationData;
// Send the update request without the `status`
const response = await http.patch( const response = await http.patch(
`/update-station/${id}`, `/update-station/${id}`,
stationData updateData
); );
toast.success("Station Deatils updated successfully"); toast.success("Station Details updated successfully");
return response?.data; return response?.data;
} catch (error: any) { } catch (error: any) {
toast.error("Error updating the user: " + error); toast.error("Error updating the station: " + error);
return rejectWithValue( return rejectWithValue(
error.response?.data?.message || "An error occurred" error.response?.data?.message || "An error occurred"
); );
} }
} }
); );
export const deleteStation = createAsyncThunk< export const deleteStation = createAsyncThunk<
string, string,
string, string,
@ -158,17 +185,30 @@ const stationSlice = createSlice({
stationList.fulfilled, stationList.fulfilled,
(state, action: PayloadAction<any>) => { (state, action: PayloadAction<any>) => {
state.loading = false; state.loading = false;
// Properly extract stations from the response data structure // Correct data extraction
state.stations = state.stations = action.payload.data?.stations || [];
action.payload.data?.results ||
action.payload.data ||
[];
} }
) )
.addCase(stationList.rejected, (state, action) => { .addCase(stationList.rejected, (state, action) => {
state.loading = false; state.loading = false;
state.error = action.payload || "Failed to fetch stations"; state.error = action.payload || "Failed to fetch stations";
}) })
.addCase(getAllStations.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(
getAllStations.fulfilled,
(state, action: PayloadAction<any>) => {
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) => { .addCase(createStation.pending, (state) => {
state.loading = true; state.loading = true;
}) })
@ -176,12 +216,12 @@ const stationSlice = createSlice({
createStation.fulfilled, createStation.fulfilled,
(state, action: PayloadAction<any>) => { (state, action: PayloadAction<any>) => {
state.loading = false; state.loading = false;
// Add the newly created station to the state if it exists in the response
if (action.payload.data) { if (action.payload.data) {
state.stations.push(action.payload.data); state.stations.push(action.payload.data);
} }
} }
) )
.addCase( .addCase(
createStation.rejected, createStation.rejected,
(state, action: PayloadAction<string | undefined>) => { (state, action: PayloadAction<string | undefined>) => {
@ -225,8 +265,21 @@ const stationSlice = createSlice({
}) })
.addCase(updateStation.fulfilled, (state, action) => { .addCase(updateStation.fulfilled, (state, action) => {
state.loading = false; 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) => { .addCase(updateStation.rejected, (state) => {
state.loading = false; state.loading = false;
}) })