From f353befab5dde620827e48a7ffac9d6beca55ebc Mon Sep 17 00:00:00 2001 From: jaanvi Date: Fri, 18 Apr 2025 18:36:20 +0530 Subject: [PATCH] dashboard login page and table ui changes --- src/components/AddSlotModal/addSlotModal.tsx | 13 +- src/components/AddUserModal/styled.css.tsx | 2 +- src/components/CustomTable/customTable.tsx | 887 +++++++----------- .../EditSlotModal/editSlotModal.tsx | 77 +- .../LineChartCard/lineChartCard.tsx | 11 +- .../ResourcePieChart/resourcePieChart.tsx | 46 +- src/components/SessionsChart/sessionChart.tsx | 5 +- src/components/StatCard/statCard.tsx | 8 +- src/components/barChartCard/barChartCard.tsx | 10 +- src/pages/Auth/Login/index.tsx | 108 ++- src/pages/EvSlotList/index.tsx | 23 +- src/pages/StationList/index.tsx | 18 +- src/redux/slices/slotSlice.ts | 77 +- src/shared-theme/AppTheme.tsx | 63 -- src/shared-theme/customizations/autoFill.tsx | 50 +- 15 files changed, 582 insertions(+), 816 deletions(-) diff --git a/src/components/AddSlotModal/addSlotModal.tsx b/src/components/AddSlotModal/addSlotModal.tsx index 2950115..f2d3fc1 100644 --- a/src/components/AddSlotModal/addSlotModal.tsx +++ b/src/components/AddSlotModal/addSlotModal.tsx @@ -43,8 +43,15 @@ const AddSlotModal = ({ open, handleClose }: any) => { }, [startHour]); const onSubmit = (data: any) => { - const { date, startingDate, endingDate, startHour, endHour, duration } = - data; + const { + date, + startingDate, + endingDate, + startHour, + endHour, + duration, + stationId, + } = data; const payload = isDateRange ? { @@ -55,6 +62,7 @@ const AddSlotModal = ({ open, handleClose }: any) => { duration: parseInt(duration, 10), durationUnit, // Include the duration unit (minutes or hours) isAvailable, + stationId, } : { date, @@ -63,6 +71,7 @@ const AddSlotModal = ({ open, handleClose }: any) => { duration: parseInt(duration, 10), durationUnit, // Include the duration unit (minutes or hours) isAvailable, + stationId, }; dispatch(createSlot(payload)); diff --git a/src/components/AddUserModal/styled.css.tsx b/src/components/AddUserModal/styled.css.tsx index ebed712..9aa47ab 100644 --- a/src/components/AddUserModal/styled.css.tsx +++ b/src/components/AddUserModal/styled.css.tsx @@ -5,7 +5,7 @@ export const CustomIconButton = styled(IconButton)({ "&:hover": { backgroundColor: "transparent", }, - "*:where([data-mui-color-scheme='dark']) &": { + "*:where([data-mui-color-scheme='light']) &": { backgroundColor: "transparent", border: "none", }, diff --git a/src/components/CustomTable/customTable.tsx b/src/components/CustomTable/customTable.tsx index 1ad9980..5554f5d 100644 --- a/src/components/CustomTable/customTable.tsx +++ b/src/components/CustomTable/customTable.tsx @@ -22,6 +22,9 @@ import { TextField, Typography, } from "@mui/material"; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; +import VisibilityIcon from "@mui/icons-material/Visibility"; import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded"; import DeleteModal from "../Modals/DeleteModal/index.tsx"; import { AppDispatch, RootState } from "../../redux/store/store.ts"; @@ -51,38 +54,33 @@ import ManagerStationDetails from "../../pages/ManagerStationDetails/index.tsx"; const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.body}`]: { fontSize: "16px", - borderBottom: "1px solid #454545", - + borderBottom: "1px solid rgba(87, 85, 85, 0.53)", + color: "#000000", + backgroundColor: "#D0E1E9", }, [`&.${tableCellClasses.head}`]: { - backgroundColor: "#454545", - color: theme.palette.common.white, - borderBottom: "none", - borderRight: "1px solid rgba(141, 135, 135, 0.51)", - // transition: "border-color 0.3s ease", + backgroundColor: "#000000", + color: "#D0E1E9", + borderBottom: "none", + //borderRight: "1px solid rgba(141, 135, 135, 0.51)", position: "sticky", - top: 0, + top: 0, zIndex: 10, - // "&:hover": { - // borderRight: "3px solid rgba(112, 109, 109, 0.8)", - // },p }, })); const StyledTableRow = styled(TableRow)(({ theme }) => ({ - "&:nth-of-type(odd)": { - backgroundColor: theme.palette.action.hover, - }, - "&:nth-of-type(even)": { - backgroundColor: theme.palette.action.hover, - }, + backgroundColor: "#D0E1E9", "& td, th": { - borderColor: "#454545", // Applying border color to both td and th - borderWidth: "1px", // Set border width to ensure it appears + borderColor: "#454545", + borderWidth: "1px", borderBottom: "1px solid #454545", + color: "#000000", + backgroundColor: "#D0E1E9", }, })); + export interface Column { id: string; label: string; @@ -103,9 +101,11 @@ interface CustomTableProps { viewModal: boolean; setViewModal: Function; deleteModal: boolean; - handleStatusToggle?: (id: string, currentStatus: number) => void; + handleStatusToggle?: (id: string, currentStatus: number | boolean) => void; tableType: string; // Adding tableType prop to change header text dynamically handleClickOpen?: () => void; + statusField?: string; // Optional field to indicate the status column + statusValue?: boolean; // Optional normalized status value } @@ -133,6 +133,69 @@ const CustomTable: React.FC = ({ const [sortOrder, setSortOrder] = React.useState<"asc" | "desc" | null>( null ); + // ... [imports remain the same, no changes needed] ... + + const getTitleByType = (type: string) => { + const titles: { [key: string]: string } = { + admin: "Admins", + role: "Roles", + user: "Users", + manager: "Managers", + "all-managers": "Managers", + vehicle: "Vehicles", + station: "Charging Station", + "external-station": "Charging Station", + booking: "Booking", + slots: "Slots", + "all-available-slots": "Available Slots", + "manager-station": "Station Details", + }; + return titles[type] || "List"; + }; + + const getAddButtonLabel = (type: string) => { + const labels: { [key: string]: string } = { + admin: "Admin", + role: "Role", + user: "User", + manager: "Manager", + vehicle: "Vehicle", + station: "Charging Station", + booking: "Booking", + slots: "Slot", + "external-station": "Location", + "manager-station": "Station Details", + }; + return labels[type] || "Item"; + }; + + const getEmptyMessage = (type: string) => { + const messages: { [key: string]: string } = { + admin: "No admins found", + role: "No roles found", + user: "No users found", + manager: "No managers found", + vehicle: "No vehicles found", + station: "No charging stations found", + "external-station": "No charging stations found", + booking: "No bookings found", + slots: "No slots found", + "all-available-slots": "No available slots found", + }; + return messages[type] || "No data available"; + }; + + const shouldShowAddButton = (userType: string, tableType: string) => { + if ( + (userType === "user" && tableType === "all-available-slots") || + (userType === "superadmin" && tableType === "all-managers") || + (userType === "superadmin" && tableType === "user") + ) { + return false; + } + return true; + }; + const handleClick = (event: React.MouseEvent, row: Row) => { setAnchorEl(event.currentTarget); setSelectedRow(row); @@ -224,21 +287,22 @@ const CustomTable: React.FC = ({ setViewModal(false); }; +const handleToggleStatus = () => { + if (selectedRow) { + handleStatusToggle?.(selectedRow.id, !selectedRow.statusValue); // Toggle the boolean statusValue + } + handleClose(); +}; - const handleToggleStatus = () => { - if (selectedRow) { - // Toggle the opposite of current status - const newStatus = selectedRow.statusValue === 1 ? 0 : 1; - handleStatusToggle?.(selectedRow.id, newStatus); - } - handleClose(); - }; - const handleSort = () => { setSortOrder((prevSortOrder) => prevSortOrder === "asc" ? "desc" : "asc" ); }; + const handleEditButton = (row: Row) => { + setModalOpen(true); + setRowData(row); + }; const sortedRows = React.useMemo(() => { let sorted = [...rows]; @@ -251,20 +315,17 @@ const CustomTable: React.FC = ({ } return sorted; }, [rows, sortOrder]); - const filteredRows = sortedRows.filter((row) => { - if (!searchQuery.trim()) return true; - const lowerCaseQuery = searchQuery.toLowerCase().trim(); - return ( - (row.name && row.name.toLowerCase().includes(lowerCaseQuery)) || - (row.registeredAddress && - row.registeredAddress - .toLowerCase() - .includes(lowerCaseQuery)) || - (row.stationName && - row.stationName.toLowerCase().includes(lowerCaseQuery)) - ); - }); - + const filteredRows = sortedRows.filter((row) => { + if (!searchQuery.trim()) return true; + const lowerCaseQuery = searchQuery.toLowerCase().trim(); + return ( + (row.name && row.name.toLowerCase().includes(lowerCaseQuery)) || + (row.registeredAddress && + row.registeredAddress.toLowerCase().includes(lowerCaseQuery)) || + (row.stationName && + row.stationName.toLowerCase().includes(lowerCaseQuery)) + ); + }); const indexOfLastRow = currentPage * usersPerPage; const indexOfFirstRow = indexOfLastRow - usersPerPage; @@ -278,194 +339,94 @@ const CustomTable: React.FC = ({ }; return ( - - - {/* Dynamic title based on the page type */} - {(() => { - switch (tableType) { - case "admin": - return "Admins"; - case "role": - return "Roles"; - case "user": - return "Users"; - case "manager": - return "Managers"; - case "all-managers": - return "Managers"; - case "vehicle": - return "Vehicles"; - case "station": - return "Charging Station"; - case "external-station": - return "Charging Station"; - case "booking": - return "Booking"; - case "slots": - return "Slots"; - case "all-available-slots": - return "Available Slots"; - case "manager-station": - return "Station Details" - default: - return "List"; - } - })()} - - - {/* Search & Buttons Section */} + - - - - ), - }, - }} - value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - /> + > + {getTitleByType(tableType)} + + {/* Right Side: Search + Add */} - {!( - (user?.userType === "user" && - tableType === "all-available-slots") || - (user?.userType === "superadmin" && - tableType === "all-managers") || - (user?.userType === "superadmin" && - tableType === "user") - ) && ( + + + + ), + }} + value={searchQuery} + onChange={(e) => setSearchQuery(e.target.value)} + /> + + {/* Conditionally show Add Button */} + {shouldShowAddButton(user?.userType, tableType) && ( )} - - {/* - - */} + {/* Table Section */} = ({ borderRadius: "4px", }, }} - > - + {" "} {columns.map((column) => ( - + {column.label} - {column.id === "name" && ( - - {sortOrder === "asc" ? ( - - ) : ( - - )} - - )} ))} - - {/* This is where the modification starts */} + {currentRows.length === 0 ? ( - {(() => { - switch (tableType) { - case "admin": - return "No admins found"; - case "role": - return "No roles found"; - case "user": - return "No users found"; - case "manager": - return "No managers found"; - case "vehicle": - return "No vehicles found"; - case "station": - return "No charging stations found"; - case "external-station": - return "No charging stations found"; - case "booking": - return "No bookings found"; - case "slots": - return "No slots found"; - case "all-available-slots": - return "No available slots found"; - default: - return "No data available"; - } - })()} + {getEmptyMessage(tableType)} ) : ( currentRows.map((row, rowIndex) => ( {columns.map((column) => ( + // In CustomTable.tsx, update the status column rendering logic inside the TableBody - {isImage(row[column.id]) ? ( + {column.id === "action" ? ( + <> + { + setSelectedRow(row); + setViewModal(true); + }} + > + + + + + handleEditButton( + row + ) + } + > + + + + { + setDeleteModal( + true + ); + setSelectedRow(row); + }} + > + + + + ) : row.statusField && + column.id === row.statusField ? ( // Check if statusField matches the column + + ) : isImage(row[column.id]) ? ( Row = ({ objectFit: "cover", }} /> - ) : column.id !== "action" ? ( - row[column.id] ) : ( - { - handleClick(e, row); - setRowData(row); - }} - sx={{ - padding: 0, - minWidth: 0, - width: "auto", - height: "auto", - color: "#FFFFFF", - }} - > - - + row[column.id] )} ))} @@ -657,232 +611,83 @@ const CustomTable: React.FC = ({
{/* Pagination */} - - {filteredRows.length > 0 && ( - <> - - Page Number : - - - - )} - - - {/* Menu Actions */} - {open && ( - + -
- + /> + - {viewModal && tableType === "admin" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "manager" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - - {viewModal && tableType === "vehicle" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "station" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - {viewModal && tableType === "user" && ( - - handleViewButton(selectedRow?.id) - } - open={viewModal} - setViewModal={setViewModal} - id={selectedRow?.id} - /> - )} - - {/* Edit Button */} - - - {tableType === "role" && ( - - )} - - {tableType === "station" && ( - - )} - - {/* Delete Button */} - -
-
+ {viewModal && tableType === "admin" && ( + handleViewButton(selectedRow?.id)} + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> )} + {viewModal && tableType === "manager" && ( + handleViewButton(selectedRow?.id)} + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> + )} + + {viewModal && tableType === "vehicle" && ( + handleViewButton(selectedRow?.id)} + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> + )} + {viewModal && tableType === "station" && ( + handleViewButton(selectedRow?.id)} + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> + )} + {viewModal && tableType === "user" && ( + handleViewButton(selectedRow?.id)} + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> + )} + + {tableType === "role" && ( + + )} + {/* Modals */} {deleteModal && ( = ({ }); const [loading, setLoading] = useState(false); - const [isAvailable, setIsAvailable] = useState( - editRow?.isAvailable || false - ); useEffect(() => { if (editRow) { setValue("startTime", editRow.startTime); setValue("endTime", editRow.endTime); - setIsAvailable(editRow.isAvailable); } else { reset(); } @@ -77,24 +73,21 @@ const EditSlotModal: React.FC = ({ setLoading(true); try { - const availabilityStatus = isAvailable ? true : false; await dispatch( updateSlot({ - id: editRow.id, // Slot ID// date: data.date, + id: editRow.id, startTime: data.startTime, endTime: data.endTime, - isAvailable: availabilityStatus, }) ).unwrap(); dispatch(fetchManagersSlots()); - handleClose(); // Close modal on success - reset(); // Reset form fields after submit + handleClose(); + reset(); } catch (error) { console.error("Error updating slot:", error); - // Handle the error or show a toast message } finally { - setLoading(false); // Stop loading state + setLoading(false); } } }; @@ -106,7 +99,7 @@ const EditSlotModal: React.FC = ({ if (reason === "backdropClick") { return; } - handleClose(); // Close modal when clicking cross or cancel + handleClose(); }} aria-labelledby="edit-slot-modal" > @@ -119,7 +112,7 @@ const EditSlotModal: React.FC = ({ left: "50%", transform: "translate(-50%, -50%)", width: 400, - bgcolor: "background.paper", + bgcolor: "#000000", boxShadow: 24, p: 3, borderRadius: 2, @@ -133,10 +126,18 @@ const EditSlotModal: React.FC = ({ alignItems: "center", }} > - + Edit Slot - +
@@ -148,7 +149,12 @@ const EditSlotModal: React.FC = ({ {/* Start Time */} - + Start Time = ({ {/* End Time */} - + End Time = ({ )} /> - - {/* Availability Toggle */} - - - {/* - {isAvailable ? "Available" : "Not Available"} - */} - {/* Submit Button */} @@ -222,12 +209,12 @@ const EditSlotModal: React.FC = ({