bulk-email/src/components/CustomTable/customTable.tsx
2025-03-31 18:28:38 +05:30

681 lines
16 KiB
TypeScript

import * as React from "react";
import { styled } from "@mui/material/styles";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell, { tableCellClasses } from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper, { paperClasses } from "@mui/material/Paper";
import { adminList, deleteAdmin } from "../../redux/slices/adminSlice.ts";
import { vehicleList, deleteVehicle } from "../../redux/slices/VehicleSlice.ts";
import { deleteManager, managerList } from "../../redux/slices/managerSlice.ts";
import { useDispatch, useSelector } from "react-redux";
import {
Box,
Button,
InputAdornment,
Menu,
IconButton,
Pagination,
TextField,
Typography,
} from "@mui/material";
import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded";
import DeleteModal from "../Modals/DeleteModal/index.tsx";
import { AppDispatch, RootState } from "../../redux/store/store.ts";
import ViewModal from "../Modals/ViewModal/index.tsx";
import VehicleViewModal from "../Modals/VehicleViewModal/index.tsx";
import SearchIcon from "@mui/icons-material/Search";
import TuneIcon from "@mui/icons-material/Tune";
import { CustomIconButton } from "../AddEditUserModel/styled.css.tsx";
import ManagerViewModal from "../Modals/ViewManagerModal/index.tsx";
import UserViewModal from "../Modals/UserViewModal/index.tsx";
import { deleteUser, userList } from "../../redux/slices/userSlice.ts";
import { deleteStation, stationList } from "../../redux/slices/stationSlice.ts";
import StationViewModal from "../Modals/StationViewModal/index.tsx";
import {
deleteSlot,
fetchAvailableSlots,
} from "../../redux/slices/slotSlice.ts";
import { bookingList, deleteBooking } from "../../redux/slices/bookSlice.ts";
// Styled components for customization
const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
backgroundColor: "#454545", // Changed to #272727 for the header
color: theme.palette.common.white,
borderBottom: "none", // Remove any border at the bottom of the header
},
[`&.${tableCellClasses.body}`]: {
fontSize: 14,
borderBottom: "1px solid #454545", // Adding border to body cells
},
}));
const StyledTableRow = styled(TableRow)(({ theme }) => ({
"&:nth-of-type(odd)": {
backgroundColor: theme.palette.action.hover,
},
"& td, th": {
borderColor: "#454545", // Applying border color to both td and th
borderWidth: "1px", // Set border width to ensure it appears
},
}));
export interface Column {
id: string;
label: string;
align?: "left" | "center" | "right";
}
interface Row {
[key: string]: any;
}
interface CustomTableProps {
columns: Column[];
rows: Row[];
setDeleteModal: Function;
setRowData: Function;
setModalOpen: Function;
viewModal: boolean;
setViewModal: Function;
deleteModal: boolean;
handleStatusToggle?: (id: string, currentStatus: number) => void;
tableType: string; // Adding tableType prop to change header text dynamically
handleClickOpen: () => void;
}
const CustomTable: React.FC<CustomTableProps> = ({
columns,
rows,
setDeleteModal,
deleteModal,
viewModal,
setRowData,
setViewModal,
setModalOpen,
handleStatusToggle,
tableType,
handleClickOpen,
}) => {
const dispatch = useDispatch<AppDispatch>();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [selectedRow, setSelectedRow] = React.useState<Row | null>(null);
const [searchQuery, setSearchQuery] = React.useState("");
const [currentPage, setCurrentPage] = React.useState(1);
const usersPerPage = 10;
const { user } = useSelector((state: RootState) => state?.profileReducer);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>, row: Row) => {
setAnchorEl(event.currentTarget);
setSelectedRow(row);
setRowData(row);
};
const handleClose = () => {
setAnchorEl(null);
};
const isImage = (value: any) => {
if (typeof value === "string") {
return value.startsWith("http") || value.startsWith("data:image"); // Check for URL or base64 image
}
return false;
};
const handleDeleteButton = (id: string | undefined) => {
if (!id) {
console.error("ID not found", id);
return;
}
switch (tableType) {
case "admin":
dispatch(deleteAdmin(id || ""));
break;
case "vehicle":
dispatch(deleteVehicle(id || ""));
break;
case "manager":
dispatch(deleteManager(id || ""));
break;
case "user":
dispatch(deleteUser(id || ""));
break;
case "station":
dispatch(deleteStation(id || ""));
break;
case "slots":
dispatch(deleteSlot(id || ""));
break;
case "booking":
dispatch(deleteBooking(id || ""));
break;
default:
console.error("Unknown table type:", tableType);
return;
}
setDeleteModal(false); // Close the modal only after deletion
handleClose();
};
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;
case "booking":
dispatch(bookingList());
break;
case "slots":
dispatch(fetchAvailableSlots());
break;
case "station":
dispatch(stationList());
break;
default:
console.error("Unknown table type:", tableType);
return;
}
setViewModal(false);
};
const handleToggleStatus = () => {
if (selectedRow) {
// Toggle the opposite of current status
const newStatus = selectedRow.statusValue === 1 ? 0 : 1;
handleStatusToggle?.(selectedRow.id, newStatus);
}
handleClose();
};
const filteredRows = rows.filter(
(row) =>
(row.name &&
row.name.toLowerCase().includes(searchQuery.toLowerCase())) ||
false
);
const indexOfLastRow = currentPage * usersPerPage;
const indexOfFirstRow = indexOfLastRow - usersPerPage;
const currentRows = filteredRows.slice(indexOfFirstRow, indexOfLastRow);
const handlePageChange = (
_event: React.ChangeEvent<unknown>,
value: number
) => {
setCurrentPage(value);
};
return (
<Box
sx={{
width: "calc(100% - 48px)",
margin: "0 auto",
padding: "24px",
backgroundColor: "#1C1C1C",
borderRadius: "12px",
}}
>
<Typography
sx={{
color: "#FFFFFF",
fontWeight: 500,
fontSize: "18px",
fontFamily: "Gilroy",
}}
>
{/* Dynamic title based on the page type */}
{(() => {
switch (tableType) {
case "admin":
return "Admin";
case "role":
return "Roles";
case "user":
return "Users";
case "manager":
return "Managers";
case "vehicle":
return "Vehicles";
case "station":
return "Charging Station";
case "booking":
return "Booking";
case "slots":
return "Slot";
default:
return "List";
}
})()}
</Typography>
{/* Search & Buttons Section */}
<Box
sx={{
display: "flex",
marginTop: "16px",
alignItems: "center",
}}
>
<TextField
variant="outlined"
placeholder="Search"
sx={{
width: "422px",
borderRadius: "12px",
input: { color: "#FFFFFF" },
backgroundColor: "#272727",
"& .MuiOutlinedInput-root": {
borderRadius: "12px",
width: "422px",
height: "44px",
borderWidth: "1px",
padding: "14px 12px 14px 12px",
gap: "16px",
"& fieldset": { borderColor: "#FFFFFF" },
"&:hover fieldset": { borderColor: "#FFFFFF" },
"&.Mui-focused fieldset": {
borderColor: "#52ACDF",
},
},
"& .MuiInputBase-input::placeholder": {
color: "#D9D8D8",
opacity: 1,
},
}}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<SearchIcon sx={{ color: "#52ACDF" }} />
</InputAdornment>
),
}}
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
width: "100%",
}}
>
{!(user?.userType === "user" && tableType === "slots") && (
<Button
sx={{
backgroundColor: "#52ACDF",
color: "white",
borderRadius: "8px",
width: "184px",
marginRight: "16px",
"&:hover": { backgroundColor: "#439BC1" },
}}
onClick={() => handleClickOpen()}
>
Add{" "}
{(() => {
switch (tableType) {
case "admin":
return "Admin";
case "role":
return "Role";
case "user":
return "User";
case "manager":
return "Manager";
case "vehicle":
return "Vehicle";
case "station":
return "Charging Station";
case "booking":
return "Booking";
case "slots":
return "Slot";
default:
return "Item";
}
})()}
</Button>
)}
</Box>
<IconButton
sx={{
width: "44px",
height: "44px",
borderRadius: "8px",
backgroundColor: "#1C1C1C",
color: "#52ACDF",
"&:hover": { backgroundColor: "#333333" },
"*:where([data-mui-color-scheme='dark']) &": {
backgroundColor: "#1C1C1C",
},
}}
>
<TuneIcon />
</IconButton>
</Box>
{/* Table Section */}
<TableContainer
component={Paper}
sx={{
marginTop: "24px",
backgroundColor: "#1C1C1C",
borderRadius: "12px",
overflow: "hidden",
}}
>
<Table>
<TableHead
sx={{
backgroundColor: "#272727",
borderBottom: "none",
".css-1ex4ubw-MuiTableCell-root.MuiTableCell-head ":
{
backgroundColor: "#272727",
},
}}
>
{" "}
<TableRow>
{columns.map((column) => (
<StyledTableCell
key={column.id}
sx={{
color: "#FFFFFF",
fontWeight: "bold",
}}
>
{column.label}
</StyledTableCell>
))}
</TableRow>
</TableHead>
<TableBody
sx={{
".MuiTableCell-root": {
backgroundColor: "#1C1C1C",
},
}}
>
{currentRows.map((row, rowIndex) => (
<StyledTableRow key={rowIndex}>
{columns.map((column) => (
<StyledTableCell
key={column.id}
sx={{
color: "#FFFFFF",
backgroundColor: "#272727",
}}
>
{isImage(row[column.id]) ? (
<img
src={row[column.id]}
alt="Row "
style={{
width: "50px",
height: "50px",
objectFit: "cover",
}}
/>
) : column.id !== "action" ? (
row[column.id]
) : (
<CustomIconButton
onClick={(e) => {
handleClick(e, row);
setRowData(row); // Store the selected row
}}
sx={{
padding: 0,
minWidth: 0,
width: "auto",
height: "auto",
color: "#FFFFFF",
}}
>
<MoreHorizRoundedIcon
sx={{ fontSize: "24px" }}
/>
</CustomIconButton>
)}
</StyledTableCell>
))}
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
{/* Pagination */}
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
alignItems: "center",
marginTop: "16px",
}}
>
<Typography
sx={{ color: "white", fontSize: "16px", fontWeight: 500 }}
>
Page Number :
</Typography>
<Pagination
count={Math.ceil(filteredRows.length / usersPerPage)}
page={currentPage}
onChange={handlePageChange}
siblingCount={0}
boundaryCount={0}
sx={{
"& .MuiPaginationItem-root": {
color: "white",
borderRadius: "0px",
},
"& .MuiPaginationItem-page.Mui-selected": {
backgroundColor: "transparent",
fontWeight: "bold",
color: "#FFFFFF",
},
}}
/>
</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",
}}
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={{
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}
/>
)}
<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>
)}
{/* Modals */}
{deleteModal && (
<DeleteModal
handleDelete={() => handleDeleteButton(selectedRow?.id)}
open={deleteModal}
setDeleteModal={setDeleteModal}
id={selectedRow?.id}
/>
)}
</Box>
);
};
export default CustomTable;