Latest changes

This commit is contained in:
Eknoor Singh 2025-03-28 11:48:26 +05:30
parent e96759ef3b
commit 87b971d97d
11 changed files with 7195 additions and 8290 deletions

File diff suppressed because it is too large Load diff

View file

@ -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) => (
<MenuItem
key={index}
value={port.chargeType}
value={port}
>
{port.chargeType}
{port}
</MenuItem>
))}
</Select>
@ -290,7 +290,6 @@ export default function AddBookingModal({
{/* Start Time and End Time */}
<Box sx={{ display: "flex", gap: 2, mb: 2 }}>
<Box sx={{ flex: 1 }}>
<Typography variant="body2" fontWeight={500}>
Start Time
@ -311,7 +310,6 @@ export default function AddBookingModal({
/>
</Box>
<Box sx={{ flex: 1 }}>
<Typography variant="body2" fontWeight={500}>
End Time
@ -487,4 +485,4 @@ export default function AddBookingModal({
</Box>
</Modal>
);
}
}

View file

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

View file

@ -46,6 +46,8 @@ export default function AddStationModal({
const vehicleBrands = useSelector(
(state: RootState) => state.vehicleReducer.vehicleBrands
);
console.log("vehicle Brands", vehicleBrands);
const [selectedBrand, setSelectedBrand] = useState<string | "">("");
useEffect(() => {
@ -86,7 +88,7 @@ export default function AddStationModal({
const payload = {
...data,
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
};

View file

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

View file

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

View file

@ -1,27 +1,37 @@
import axios from "axios";
// import { useHistory } from "react-router-dom";
const http = axios.create({
baseURL: process.env.REACT_APP_BACKEND_URL,
});
http.interceptors.request.use((config) => {
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);
}
);

View file

@ -88,9 +88,13 @@ 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

View file

@ -37,11 +37,10 @@ export const fetchVehicleBrands = createAsyncThunk<
if (!response.data || !Array.isArray(response.data.data)) {
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
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
}));
return response.data.data;
} catch (error: any) {
return rejectWithValue("Failed to fetch vehicle brands");
}

View file

@ -60,7 +60,9 @@ 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(
error?.response?.data?.message || "An error occurred"
@ -171,4 +173,4 @@ const bookSlice = createSlice({
},
});
export default bookSlice.reducer;
export default bookSlice.reducer;

View file

@ -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<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
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<any>) => {
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<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) => {
state.loading = true;
})
@ -176,12 +216,12 @@ const stationSlice = createSlice({
createStation.fulfilled,
(state, action: PayloadAction<any>) => {
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<string | undefined>) => {
@ -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;
})
@ -245,4 +298,4 @@ const stationSlice = createSlice({
},
});
export default stationSlice.reducer;
export default stationSlice.reducer;