after pull changes
This commit is contained in:
commit
23d4dbaabd
|
@ -47,59 +47,58 @@ export default function AddStationModal({
|
|||
(state: RootState) => state.vehicleReducer.vehicleBrands
|
||||
);
|
||||
|
||||
console.log("vehicle Brands", vehicleBrands);
|
||||
const [selectedBrand, setSelectedBrand] = useState<string | "">("");
|
||||
|
||||
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<string[]>([]);
|
||||
const [selectedVehicles, setSelectedVehicles] = useState<string[]>([]);
|
||||
|
||||
// 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
|
||||
allowedCars: vehicleIds, // Pass the vehicle ids to the backend
|
||||
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 (
|
||||
|
@ -253,7 +252,7 @@ export default function AddStationModal({
|
|||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Vehicle Name Dropdown with Checkboxes */}
|
||||
{/* Vehicle Brand Dropdown with Checkboxes */}
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
|
@ -263,26 +262,33 @@ export default function AddStationModal({
|
|||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Select Vehicle Brand
|
||||
Select Vehicle Brands
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>Choose Brand</InputLabel>
|
||||
<InputLabel>Choose Brands</InputLabel>
|
||||
<Select
|
||||
value={selectedBrand}
|
||||
onChange={(e) =>
|
||||
setSelectedBrand(e.target.value)
|
||||
multiple
|
||||
value={selectedBrands}
|
||||
onChange={handleBrandChange}
|
||||
renderValue={(selected) =>
|
||||
(selected as string[]).join(", ")
|
||||
}
|
||||
label="Choose Brand"
|
||||
label="Choose Brands"
|
||||
>
|
||||
{Array.isArray(vehicleBrands) &&
|
||||
vehicleBrands.length > 0 ? (
|
||||
{vehicleBrands.length > 0 ? (
|
||||
vehicleBrands.map((brand) => (
|
||||
<MenuItem
|
||||
key={brand.id}
|
||||
value={brand.id}
|
||||
>
|
||||
{brand.name}{" "}
|
||||
{/* Make sure 'brand.id' is set as value */}
|
||||
<Checkbox
|
||||
checked={selectedBrands.includes(
|
||||
brand.id
|
||||
)}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={brand.name}
|
||||
/>
|
||||
</MenuItem>
|
||||
))
|
||||
) : (
|
||||
|
@ -298,8 +304,9 @@ export default function AddStationModal({
|
|||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Box>
|
||||
|
||||
|
||||
{/* Vehicle Name Dropdown with Checkboxes */}
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
@ -316,7 +323,7 @@ export default function AddStationModal({
|
|||
<Select
|
||||
multiple
|
||||
value={selectedVehicles}
|
||||
onChange={handleCheckboxChange}
|
||||
onChange={handleVehicleChange}
|
||||
renderValue={(selected) =>
|
||||
(selected as string[]).join(", ")
|
||||
}
|
||||
|
@ -339,8 +346,8 @@ export default function AddStationModal({
|
|||
))
|
||||
) : (
|
||||
<MenuItem disabled>
|
||||
No vehicles available for this
|
||||
brand
|
||||
No vehicles available for the
|
||||
selected brands
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
|
|
|
@ -83,6 +83,36 @@ export default function AddVehicleModal({
|
|||
>
|
||||
{/* First Row - Two Inputs */}
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Company Name
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
placeholder="Enter Company Name"
|
||||
size="small"
|
||||
error={!!errors.company}
|
||||
helperText={
|
||||
errors.company
|
||||
? errors.company.message
|
||||
: ""
|
||||
}
|
||||
{...register("company", {
|
||||
required: "Company is required",
|
||||
minLength: {
|
||||
value: 3,
|
||||
message:
|
||||
"Company must be at least 5 characters long",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
@ -121,37 +151,6 @@ export default function AddVehicleModal({
|
|||
})}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Company
|
||||
</Typography>
|
||||
<CustomTextField
|
||||
fullWidth
|
||||
placeholder="Enter Company Name"
|
||||
size="small"
|
||||
error={!!errors.company}
|
||||
helperText={
|
||||
errors.company
|
||||
? errors.company.message
|
||||
: ""
|
||||
}
|
||||
{...register("company", {
|
||||
required: "Company is required",
|
||||
minLength: {
|
||||
value: 3,
|
||||
message:
|
||||
"Company must be at least 5 characters long",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Second Row - Two Inputs */}
|
||||
|
|
|
@ -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<CustomTableProps> = ({
|
|||
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<CustomTableProps> = ({
|
|||
/>
|
||||
</Box>
|
||||
{/* Menu Actions */}
|
||||
{open &&
|
||||
(
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
id="menu"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
onClick={handleClose}
|
||||
transformOrigin={{
|
||||
horizontal: "right",
|
||||
vertical: "top",
|
||||
}}
|
||||
anchorOrigin={{
|
||||
horizontal: "right",
|
||||
vertical: "bottom",
|
||||
{open && (
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
id="menu"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
onClick={handleClose}
|
||||
transformOrigin={{
|
||||
horizontal: "right",
|
||||
vertical: "top",
|
||||
}}
|
||||
anchorOrigin={{
|
||||
horizontal: "right",
|
||||
vertical: "bottom",
|
||||
}}
|
||||
sx={{
|
||||
[`& .${paperClasses.root}`]: {
|
||||
padding: 0,
|
||||
},
|
||||
"& .MuiList-root": {
|
||||
background: "#272727", // Remove any divider under menu items
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "flex-start",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
// setSelectedRow(row);
|
||||
setViewModal(true);
|
||||
}}
|
||||
color="primary"
|
||||
sx={{
|
||||
[`& .${paperClasses.root}`]: {
|
||||
padding: 0,
|
||||
},
|
||||
"& .MuiList-root": {
|
||||
background: "#272727", // Remove any divider under menu items
|
||||
},
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
color: "#52ACDF",
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
View
|
||||
</Button>
|
||||
{viewModal && tableType === "admin" && (
|
||||
<ViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "vehicle" && (
|
||||
<VehicleViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "manager" && (
|
||||
<ManagerViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "user" && (
|
||||
<UserViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "station" && (
|
||||
<StationViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => setModalOpen(true)}
|
||||
color="primary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
{tableType === "role" && (
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleToggleStatus();
|
||||
}}
|
||||
color="secondary"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
// setSelectedRow(row);
|
||||
setViewModal(true);
|
||||
}}
|
||||
color="primary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
color: "#52ACDF",
|
||||
}}
|
||||
>
|
||||
View
|
||||
</Button>
|
||||
{viewModal && tableType === "admin" && (
|
||||
<ViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "vehicle" && (
|
||||
<VehicleViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "manager" && (
|
||||
<ManagerViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "user" && (
|
||||
<UserViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{viewModal && tableType === "station" && (
|
||||
<StationViewModal
|
||||
handleView={() =>
|
||||
handleViewButton(selectedRow?.id)
|
||||
}
|
||||
open={viewModal}
|
||||
setViewModal={setViewModal}
|
||||
id={selectedRow?.id}
|
||||
/>
|
||||
)}
|
||||
{selectedRow?.statusValue === 1
|
||||
? "Deactivate"
|
||||
: "Activate"}
|
||||
</Button>
|
||||
)}
|
||||
{tableType === "station" && (
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleToggleStatus();
|
||||
}}
|
||||
color="secondary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{selectedRow?.statusValue === 1
|
||||
? "Not Available"
|
||||
: "Available"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={() => setModalOpen(true)}
|
||||
color="primary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
textTransform: "capitalize",
|
||||
}}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
{tableType === "role" && (
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleToggleStatus();
|
||||
}}
|
||||
color="secondary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{selectedRow?.statusValue === 1
|
||||
? "Deactivate"
|
||||
: "Activate"}
|
||||
</Button>
|
||||
)}
|
||||
{tableType === "station" && (
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleToggleStatus();
|
||||
}}
|
||||
color="secondary"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
{selectedRow?.statusValue === 1
|
||||
? "Not Available"
|
||||
: "Available"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setDeleteModal(true);
|
||||
}}
|
||||
color="error"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</Box>
|
||||
</Menu>
|
||||
)}
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setDeleteModal(true);
|
||||
}}
|
||||
color="error"
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
py: 0,
|
||||
fontWeight: "bold",
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</Box>
|
||||
</Menu>
|
||||
)}
|
||||
{/* Modals */}
|
||||
{deleteModal && (
|
||||
<DeleteModal
|
||||
|
|
|
@ -74,9 +74,7 @@ const EditManagerModal: React.FC<EditManagerModalProps> = ({
|
|||
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
|
||||
|
|
|
@ -52,12 +52,12 @@ const EditSlotModal: React.FC<EditSlotModalProps> = ({
|
|||
const [loading, setLoading] = useState(false);
|
||||
const [isAvailable, setIsAvailable] = useState<boolean>(
|
||||
editRow?.isAvailable || false
|
||||
); // Default to editRow availability
|
||||
);
|
||||
|
||||
// Set values if editRow is provided
|
||||
useEffect(() => {
|
||||
if (editRow) {
|
||||
setValue("date", editRow.date);
|
||||
// setValue("date", editRow.date);
|
||||
setValue("startTime", editRow.startTime);
|
||||
setValue("endTime", editRow.endTime);
|
||||
setIsAvailable(editRow.isAvailable); // Set the initial availability correctly
|
||||
|
@ -68,27 +68,28 @@ const EditSlotModal: React.FC<EditSlotModalProps> = ({
|
|||
|
||||
const onSubmit = async (data: FormData) => {
|
||||
if (editRow) {
|
||||
setLoading(true); // Start loading
|
||||
|
||||
try {
|
||||
// Convert boolean availability to 1/0
|
||||
const availabilityStatus = isAvailable ? true : false;
|
||||
|
||||
await dispatch(
|
||||
updateSlot({
|
||||
id: editRow.id, // Slot ID
|
||||
slotData: {
|
||||
date: data.date,
|
||||
startTime: data.startTime,
|
||||
endTime: data.endTime,
|
||||
isAvailable: availabilityStatus,
|
||||
},
|
||||
id: editRow.id, // Slot ID// date: data.date,
|
||||
startTime: data.startTime,
|
||||
endTime: data.endTime,
|
||||
isAvailable: availabilityStatus,
|
||||
})
|
||||
).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
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ const EditSlotModal: React.FC<EditSlotModalProps> = ({
|
|||
{/* Input Fields */}
|
||||
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 2 }}>
|
||||
{/* Date */}
|
||||
<Box sx={{ flex: "1 1 100%" }}>
|
||||
{/* <Box sx={{ flex: "1 1 100%" }}>
|
||||
<Typography variant="body2" fontWeight={500} mb={0.5}>
|
||||
Date
|
||||
</Typography>
|
||||
|
@ -162,7 +163,7 @@ const EditSlotModal: React.FC<EditSlotModalProps> = ({
|
|||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Box> */}
|
||||
|
||||
{/* Start Time */}
|
||||
<Box sx={{ flex: "1 1 48%" }}>
|
||||
|
|
|
@ -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<EditStationModalProps> = ({
|
||||
|
@ -46,54 +51,82 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
handleClose,
|
||||
handleUpdate,
|
||||
editRow,
|
||||
vehicles,
|
||||
}) => {
|
||||
const { control, handleSubmit, setValue, reset, watch } = useForm<FormData>(
|
||||
{
|
||||
defaultValues: {
|
||||
name: "",
|
||||
registeredAddress: "",
|
||||
totalSlots: 0,
|
||||
status: 1,
|
||||
allowedCarIds: [],
|
||||
},
|
||||
}
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
reset,
|
||||
watch,
|
||||
formState: { errors },
|
||||
} = useForm<FormData>({
|
||||
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<string | "">("");
|
||||
const [selectedVehicles, setSelectedVehicles] = useState<string[]>([]);
|
||||
|
||||
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<EditStationModalProps> = ({
|
|||
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<EditStationModalProps> = ({
|
|||
{/* Horizontal Line */}
|
||||
<Box sx={{ borderBottom: "1px solid #ddd", my: 2 }} />
|
||||
|
||||
{/* Input Fields */}
|
||||
{/* Form */}
|
||||
<Box sx={{ display: "flex", flexDirection: "column", gap: 2 }}>
|
||||
{/* First Row - Two Inputs */}
|
||||
{/* Station Name and Address */}
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
|
@ -168,11 +201,16 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
fullWidth
|
||||
placeholder="Enter Station Name"
|
||||
size="small"
|
||||
error={!!errors.name}
|
||||
helperText={
|
||||
errors.name
|
||||
? errors.name.message
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
@ -196,13 +234,20 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
fullWidth
|
||||
placeholder="Enter Registered Address"
|
||||
size="small"
|
||||
error={!!errors.registeredAddress}
|
||||
helperText={
|
||||
errors.registeredAddress
|
||||
? errors.registeredAddress
|
||||
.message
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Second Row - Total Slots */}
|
||||
{/* Total Slots */}
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
|
@ -228,61 +273,107 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
placeholder="Enter Total Slots"
|
||||
size="small"
|
||||
type="number"
|
||||
error={!!errors.totalSlots}
|
||||
helperText={
|
||||
errors.totalSlots
|
||||
? errors.totalSlots.message
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Vehicle Dropdown with Checkboxes */}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Vehicle Names
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>Choose Vehicles</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
value={allowedCarIds || []} // Watch the allowedCarIds to reflect selected values
|
||||
onChange={(e) => {
|
||||
// Update the allowedCarIds when the selection changes
|
||||
setValue(
|
||||
"allowedCarIds",
|
||||
e.target.value as string[]
|
||||
); // Update allowedCarIds on change
|
||||
}}
|
||||
renderValue={(selected) => {
|
||||
return (selected as string[])
|
||||
.map((id) => {
|
||||
const vehicle = vehicles?.find(
|
||||
(vehicle) => vehicle.id === id
|
||||
);
|
||||
return vehicle ? vehicle.name : "";
|
||||
})
|
||||
.join(", ");
|
||||
}}
|
||||
>
|
||||
{vehicles?.map((vehicle) => (
|
||||
<MenuItem
|
||||
key={vehicle.id}
|
||||
value={vehicle.id}
|
||||
>
|
||||
<Checkbox
|
||||
checked={allowedCarIds?.includes(
|
||||
vehicle.id
|
||||
)}
|
||||
/>
|
||||
<ListItemText primary={vehicle.name} />
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
{/* Vehicle Brand Selection */}
|
||||
<Box sx={{ display: "flex", gap: 2 }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Select Vehicle Brand
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>Choose Brand</InputLabel>
|
||||
<Select
|
||||
value={selectedBrand}
|
||||
onChange={(e) =>
|
||||
setSelectedBrand(e.target.value)
|
||||
}
|
||||
label="Choose Brand"
|
||||
>
|
||||
{vehicleBrands.length > 0 ? (
|
||||
vehicleBrands.map((brand) => (
|
||||
<MenuItem
|
||||
key={brand.id}
|
||||
value={brand.id}
|
||||
>
|
||||
{brand.name}
|
||||
</MenuItem>
|
||||
))
|
||||
) : (
|
||||
<MenuItem disabled>
|
||||
No vehicle brands available
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
|
||||
{/* Vehicle Selection with Checkboxes */}
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" fontWeight={500}>
|
||||
Vehicle Name
|
||||
</Typography>
|
||||
<FormControl fullWidth>
|
||||
<InputLabel>Choose Vehicles</InputLabel>
|
||||
<Select
|
||||
multiple
|
||||
value={selectedVehicles}
|
||||
onChange={handleCheckboxChange}
|
||||
renderValue={(selected) =>
|
||||
(selected as string[]).join(", ")
|
||||
}
|
||||
>
|
||||
{filteredVehicles.length > 0 ? (
|
||||
filteredVehicles.map((vehicle) => (
|
||||
<MenuItem
|
||||
key={vehicle.id}
|
||||
value={vehicle.name}
|
||||
>
|
||||
<Checkbox
|
||||
checked={selectedVehicles.includes(
|
||||
vehicle.name
|
||||
)}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={vehicle.name}
|
||||
/>
|
||||
</MenuItem>
|
||||
))
|
||||
) : (
|
||||
<MenuItem disabled>
|
||||
No vehicles available for this brand
|
||||
</MenuItem>
|
||||
)}
|
||||
</Select>
|
||||
<FormHelperText>
|
||||
{errors.allowedCarIds
|
||||
? errors.allowedCarIds.message
|
||||
: ""}
|
||||
</FormHelperText>
|
||||
</FormControl>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
@ -300,7 +391,7 @@ const EditStationModal: React.FC<EditStationModalProps> = ({
|
|||
"&:hover": { backgroundColor: "#439BC1" },
|
||||
}}
|
||||
>
|
||||
Update Charging Station
|
||||
Update Station
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
|
|
@ -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<AppDispatch>();
|
||||
const { user } = useSelector(
|
||||
(state: RootState) => state?.profileReducer
|
||||
);
|
||||
const dispatch = useDispatch<AppDispatch>();
|
||||
const { user } = useSelector((state: RootState) => state?.profileReducer);
|
||||
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchAdminProfile());
|
||||
}, [dispatch]);
|
||||
React.useEffect(() => {
|
||||
dispatch(fetchAdminProfile());
|
||||
}, [dispatch]);
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
|
@ -89,7 +88,6 @@ export default function Header() {
|
|||
display: { xs: "none", sm: "flex" }, // Hide on mobile, show on larger screens
|
||||
}}
|
||||
>
|
||||
|
||||
<NotificationsNoneIcon onClick={toggleNotifications} />
|
||||
<Avatar
|
||||
alt="User Avatar"
|
||||
|
|
|
@ -66,9 +66,9 @@ export default function MenuContent({ hidden }: PropType) {
|
|||
url: "/panel/vehicle-list", // Placeholder for now
|
||||
},
|
||||
// userRole === "manager" && {
|
||||
// text: "Add Slots",
|
||||
// icon: <ManageAccountsOutlinedIcon />,
|
||||
// url: "/panel/EVslots", // Placeholder for now
|
||||
// text: "Add Slots",
|
||||
// icon: <ManageAccountsOutlinedIcon />,
|
||||
// url: "/panel/EVslots", // Placeholder for now
|
||||
// },
|
||||
userRole === "user" && {
|
||||
text: "Bookings",
|
||||
|
|
|
@ -32,7 +32,7 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
(state: RootState) => state.managerReducer
|
||||
);
|
||||
const [selectedManager, setSelectedManager] = useState<any>(null);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
|
||||
|
@ -110,7 +110,8 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
<Typography variant="body1">
|
||||
<strong>Station Location:</strong>
|
||||
<Typography variant="body2">
|
||||
{selectedManager.registeredAddress}
|
||||
{selectedManager.chargingStation
|
||||
?.registeredAddress || "Not Available"}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
@ -118,7 +119,8 @@ export default function ManagerViewModal({ open, setViewModal, id }: Props) {
|
|||
<Typography variant="body1">
|
||||
<strong>Station Name:</strong>
|
||||
<Typography variant="body2">
|
||||
{selectedManager.stationName}
|
||||
{selectedManager.chargingStation?.name ||
|
||||
"Not Available"}
|
||||
</Typography>
|
||||
</Typography>
|
||||
</Grid>
|
||||
|
|
|
@ -50,12 +50,8 @@ const DashboardLayout: React.FC<LayoutProps> = ({ customStyles }) => {
|
|||
...customStyles,
|
||||
mt: { xs: 8, md: 0 },
|
||||
padding: 0,
|
||||
|
||||
})}
|
||||
>
|
||||
|
||||
|
||||
|
||||
<Stack
|
||||
spacing={2}
|
||||
sx={{
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
} from "../../redux/slices/slotSlice";
|
||||
import AddSlotModal from "../../components/AddSlotModal";
|
||||
import dayjs from "dayjs";
|
||||
import EditManagerModal from "../../components/EditManagerModal";
|
||||
import EditSlotModal from "../../components/EditSlotModal";
|
||||
export default function EVSlotList() {
|
||||
const [addModalOpen, setAddModalOpen] = useState<boolean>(false);
|
||||
|
@ -56,31 +55,35 @@ 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
|
||||
) => {
|
||||
try {
|
||||
// Update manager with stationId
|
||||
await dispatch(
|
||||
updateSlot({
|
||||
id,
|
||||
date,
|
||||
startTime,
|
||||
endTime,
|
||||
isAvailable,
|
||||
})
|
||||
);
|
||||
await dispatch(fetchAvailableSlots()); // Refresh the list after update
|
||||
handleCloseModal(); // Close modal after update
|
||||
} catch (error) {
|
||||
console.error("Update failed", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdate = async (
|
||||
id: string,
|
||||
startTime: string,
|
||||
endTime: string,
|
||||
isAvailable: boolean
|
||||
) => {
|
||||
try {
|
||||
// Convert times to 24-hour format if needed
|
||||
const formattedStartTime = dayjs(startTime, "HH:mm").format("HH:mm");
|
||||
const formattedEndTime = dayjs(endTime, "HH:mm").format("HH:mm");
|
||||
|
||||
await dispatch(
|
||||
updateSlot({
|
||||
id,
|
||||
startTime: formattedStartTime, // Ensure it matches backend expectation
|
||||
endTime: formattedEndTime, // Ensure it matches backend expectation
|
||||
isAvailable,
|
||||
})
|
||||
).unwrap(); // This helps catch and handle any errors
|
||||
|
||||
await dispatch(fetchAvailableSlots()); // Refresh the list
|
||||
handleCloseModal(); // Close the modal
|
||||
} catch (error) {
|
||||
console.error("Update failed", error);
|
||||
// Optionally add error toast or user notification
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const slotColumns: Column[] = [
|
||||
{ id: "srno", label: "Sr No" },
|
||||
|
@ -95,25 +98,24 @@ export default function EVSlotList() {
|
|||
|
||||
// Make sure dayjs is imported
|
||||
|
||||
const slotRows = availableSlots?.length
|
||||
? availableSlots.map((slot, index) => {
|
||||
const formattedDate = dayjs(slot?.date).format("YYYY-MM-DD");
|
||||
const startTime = dayjs(slot?.startTime).format("HH:mm");
|
||||
const endTime = dayjs(slot?.endTime).format("HH:mm");
|
||||
console.log("availability", availableSlots.isAvailable);
|
||||
console.log("first", startTime);
|
||||
return {
|
||||
srno: index + 1,
|
||||
id: slot?.id ?? "NA",
|
||||
stationId: slot?.stationId ?? "NA",
|
||||
name: slot?.ChargingStation?.name ?? "NA",
|
||||
date: formattedDate ?? "NA",
|
||||
startTime: startTime ?? "NA",
|
||||
endTime: endTime ?? "NA",
|
||||
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
||||
};
|
||||
})
|
||||
: [];
|
||||
const slotRows = availableSlots?.length
|
||||
? availableSlots.map((slot, index) => {
|
||||
const formattedDate = dayjs(slot?.date).format("YYYY-MM-DD");
|
||||
const startTime = dayjs(slot?.startTime).format("HH:mm");
|
||||
const endTime = dayjs(slot?.endTime).format("HH:mm");
|
||||
|
||||
return {
|
||||
srno: index + 1,
|
||||
id: slot?.id ?? "NA",
|
||||
stationId: slot?.stationId ?? "NA",
|
||||
name: slot?.ChargingStation?.name ?? "NA",
|
||||
date: formattedDate ?? "NA",
|
||||
startTime: startTime ?? "NA",
|
||||
endTime: endTime ?? "NA",
|
||||
isAvailable: slot?.isAvailable ? "Yes" : "No",
|
||||
};
|
||||
})
|
||||
: [];
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
@ -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 {
|
||||
|
@ -89,12 +90,13 @@ export default function StationList() {
|
|||
};
|
||||
|
||||
const filterStations = Array.isArray(stations)
|
||||
? stations.filter((station) =>
|
||||
station.name
|
||||
.toLocaleLowerCase()
|
||||
.includes(searchTerm.toLowerCase())
|
||||
)
|
||||
: [];
|
||||
? stations.filter((station) =>
|
||||
station.name
|
||||
.toLocaleLowerCase()
|
||||
.includes(searchTerm.toLowerCase())
|
||||
)
|
||||
: [];
|
||||
|
||||
|
||||
// Mapping and formatting vehicles
|
||||
const categoryRows = filterStations?.length
|
||||
|
@ -126,6 +128,7 @@ export default function StationList() {
|
|||
};
|
||||
})
|
||||
: [];
|
||||
console.log("Rowssss",categoryRows)
|
||||
|
||||
const categoryColumns: Column[] = [
|
||||
{ id: "srno", label: "Sr No" },
|
||||
|
|
|
@ -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,18 +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");
|
||||
}
|
||||
|
||||
console.log("beans", response.data.data)
|
||||
// Assuming that 'data' contains an array of objects with a 'company' field
|
||||
return response.data.data;
|
||||
// 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,
|
||||
|
@ -157,6 +163,7 @@ const vehicleSlice = createSlice({
|
|||
state.vehicleBrands = action.payload;
|
||||
}
|
||||
)
|
||||
|
||||
.addCase(fetchVehicleBrands.rejected, (state, action) => {
|
||||
state.loading = false;
|
||||
state.error =
|
||||
|
|
|
@ -60,7 +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) {
|
||||
|
@ -121,7 +121,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,
|
||||
|
@ -169,7 +184,32 @@ const bookSlice = createSlice({
|
|||
(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";
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,16 +88,23 @@ 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;
|
||||
isAvailable: boolean;
|
||||
},
|
||||
{ rejectValue: string }
|
||||
>("slots/updateSlot", async ({ id, ...slotData }, { rejectWithValue }) => {
|
||||
try {
|
||||
const response = await http.patch(
|
||||
`/update-availability/${id}`,
|
||||
slotData
|
||||
);
|
||||
const response = await http.patch(`/update-availability/${id}`, {
|
||||
...slotData,
|
||||
// Ensure data matches exactly what backend expects
|
||||
startHour: slotData.startTime,
|
||||
endHour: slotData.endTime,
|
||||
});
|
||||
toast.success("Slot updated successfully");
|
||||
return response.data.data; // Return updated slot data
|
||||
return response.data.data;
|
||||
} catch (error: any) {
|
||||
toast.error("Error updating the slot: " + error?.message);
|
||||
return rejectWithValue(
|
||||
|
@ -167,14 +174,15 @@ const slotSlice = createSlice({
|
|||
(state, action: PayloadAction<Slot>) => {
|
||||
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;
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
.addCase(updateSlot.rejected, (state, action) => {
|
||||
state.loading = false;
|
||||
state.error = action.payload || "Failed to update slot";
|
||||
|
|
Loading…
Reference in a new issue