diff --git a/public/DigiEVLogo.png b/public/DigiEVLogo.png new file mode 100644 index 0000000..6b9434f Binary files /dev/null and b/public/DigiEVLogo.png differ diff --git a/public/Digilogo.png b/public/Digilogo.png new file mode 100644 index 0000000..1a7d127 Binary files /dev/null and b/public/Digilogo.png differ diff --git a/public/digimantra_labs_logo.jpeg b/public/digimantra_labs_logo.jpeg new file mode 100644 index 0000000..eb470ea Binary files /dev/null and b/public/digimantra_labs_logo.jpeg differ diff --git a/src/components/AddSlotModal/index.tsx b/src/components/AddSlotModal/index.tsx new file mode 100644 index 0000000..9810e84 --- /dev/null +++ b/src/components/AddSlotModal/index.tsx @@ -0,0 +1,316 @@ +import React, { useEffect, useState } from "react"; +import { + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Button, + Typography, + IconButton, + Box, + Snackbar, + Stack, + Tabs, + Tab, + Card, +} from "@mui/material"; + +import { CustomTextField } from "../../components/AddEditUserModel/styled.css.tsx"; +import AddCircleIcon from "@mui/icons-material/AddCircle"; +import DeleteIcon from "@mui/icons-material/Delete"; +import CalendarTodayRoundedIcon from "@mui/icons-material/CalendarTodayRounded"; +import { LocalizationProvider, DatePicker } from "@mui/x-date-pickers"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import dayjs from "dayjs"; +import { useDispatch, useSelector } from "react-redux"; +import { + fetchAvailableSlots, + createSlot, + deleteSlot, +} from "../../redux/slices/slotSlice.ts"; + + +const days = [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +]; + +interface AddSlotModalProps { + open: boolean; + onClose: () => void; +} + +export default function AddSlotModal({ open, onClose }: AddSlotModalProps) { + const [selectedDay, setSelectedDay] = useState("Monday"); + const [openingTime, setOpeningTime] = useState(""); + const [closingTime, setClosingTime] = useState(""); + const [breakTime, setBreakTime] = useState([]); + const [error, setError] = useState(""); + const [successMessage, setSuccessMessage] = useState(null); + const [selectedDate, setSelectedDate] = useState( + dayjs() + ); + const dispatch = useDispatch(); + + // Fetch slots from the Redux state + const { + slots, + loading, + error: apiError, + } = useSelector((state: any) => state.slotReducer.slots); + + // useEffect(() => { + // if (selectedDay) { + // dispatch(fetchAvailableSlots(1)); // Replace with actual stationId if needed + // } + // }, [dispatch, selectedDay]); + + const addSlot = (start: string, end: string) => { + const selectedDateFormatted = selectedDate.format("YYYY-MM-DD"); + const startTime = start; + const endTime = end; + + dispatch( + createSlot({ + stationId: 1, + date: selectedDateFormatted, + startHour: startTime, + endHour: endTime, + isAvailable: true, + }) + ); + }; + + const addBreak = (start: string, end: string) => { + if (!start || !end) { + setError("Break Start and End times are required."); + return; + } + + setBreakTime([...breakTime, { start, end }]); + setError(""); + }; + + const deleteSlot = (start: string, end: string) => { + const updatedSlots = slots[selectedDay].filter( + (slot: any) => !(slot.start === start && slot.end === end) + ); + setSlots({ + ...slots, + [selectedDay]: updatedSlots, + }); + }; + + const deleteBreak = (start: string, end: string) => { + const updatedBreaks = breakTime.filter( + (breakItem: any) => + !(breakItem.start === start && breakItem.end === end) + ); + setBreakTime(updatedBreaks); + }; + + const saveData = () => { + if (!openingTime || !closingTime) { + setError("Operating hours are required."); + return; + } + + setSuccessMessage( + `Data for ${selectedDay} has been saved successfully!` + ); + setError(""); + }; + + const handleCloseSnackbar = () => { + setSuccessMessage(null); + }; + + return ( + + EV Station Slot Management + + {/* Date Picker */} + + + Select Date + + + setSelectedDate(newDate)} + renderInput={(props) => ( + + ), + }} + /> + )} + /> + + + + setSelectedDay(newValue)} + variant="scrollable" + scrollButtons="auto" + sx={{ mt: 3 }} + > + {days.map((day) => ( + + ))} + + + {/* Operating Hours */} + + + Set Operating Hours for {selectedDay} + + + setOpeningTime(e.target.value)} + fullWidth + /> + setClosingTime(e.target.value)} + fullWidth + /> + + + + {/* Slots */} + + Add Slots + + + + + + {error && ( + + {error} + + )} + + + {/* Break Time */} + + Break Time + + + + + + + + {/* Slots and Break Times Lists */} + {/* (Content for slots and breaks remains the same as in the original implementation) */} + + {/* Success Snackbar */} + + + + + + + + + ); +} + + diff --git a/src/components/CustomTable/index.tsx b/src/components/CustomTable/index.tsx index 75acf87..11e9866 100644 --- a/src/components/CustomTable/index.tsx +++ b/src/components/CustomTable/index.tsx @@ -36,6 +36,7 @@ import UserViewModal from "../Modals/UserViewModal/index.tsx"; import { deleteUser, userList } from "../../redux/slices/userSlice.ts"; import { deleteStation } from "../../redux/slices/stationSlice.ts"; import StationViewModal from "../Modals/StationViewModal/index.tsx"; +import { fetchAvailableSlots } from "../../redux/slices/slotSlice.ts"; // Styled components for customization const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { @@ -159,23 +160,26 @@ const CustomTable: React.FC = ({ const handleViewButton = (id: string | undefined) => { if (!id) console.error("ID not found", id); - // switch (tableType) { - // case "admin": - // dispatch(adminList()); - // break; - // case "vehicle": - // dispatch(vehicleList()); - // break; - // case "manager": - // dispatch(managerList()); - // break; - // case "user": - // dispatch(userList()); - // break; - // default: - // console.error("Unknown table type:", tableType); - // return; - // } + switch (tableType) { + case "admin": + dispatch(adminList()); + break; + case "vehicle": + dispatch(vehicleList()); + break; + case "manager": + dispatch(managerList()); + break; + case "user": + dispatch(userList()); + break; + case "slot": + dispatch(fetchAvailableSlots(1)); + break; + default: + console.error("Unknown table type:", tableType); + return; + } setViewModal(false); }; diff --git a/src/components/MenuContent/index.tsx b/src/components/MenuContent/index.tsx index afb0d33..becee06 100644 --- a/src/components/MenuContent/index.tsx +++ b/src/components/MenuContent/index.tsx @@ -65,6 +65,11 @@ export default function MenuContent({ hidden }: PropType) { icon: , url: "/panel/EVslots", // Placeholder for now }, + userRole === "manager" && { + text: "Slot List", + icon: , + url: "/panel/slot-list", // Placeholder for now + }, ]; const filteredMenuItems = baseMenuItems.filter(Boolean); diff --git a/src/components/SideMenu/index.tsx b/src/components/SideMenu/index.tsx index 0838f94..f5b2f2b 100644 --- a/src/components/SideMenu/index.tsx +++ b/src/components/SideMenu/index.tsx @@ -55,6 +55,52 @@ export default function SideMenu() { }, }} > + + + + + {/* Digi EV Text Section */} + + Digi EV + + + {user?.userType || "N/A"} + + + + +