From 25b0ecf11130b923a16a995a871bb2d2783c92ec Mon Sep 17 00:00:00 2001 From: jaanvi Date: Fri, 28 Feb 2025 09:35:31 +0530 Subject: [PATCH 1/4] Add responsiveness and restrict admins --- src/components/AddEditRoleModal/index.tsx | 300 ----------------- src/components/CustomTable/index.tsx | 104 +++--- src/components/LineChartCard/index.tsx | 2 +- src/components/MainGrid/index.tsx | 1 + src/components/MenuContent/index.tsx | 63 ++-- src/components/ResourcePieChart/index.tsx | 3 +- src/components/SessionsChart/index.tsx | 3 +- src/components/barChartCard/index.tsx | 23 +- src/layouts/DashboardLayout/index.tsx | 110 ++++--- src/pages/AddEditRolePage/index.tsx | 283 ++++++++++++++++ src/pages/AdminList/index.tsx | 373 +--------------------- src/pages/Auth/Login/index.tsx | 108 ++++--- src/pages/RoleList/index.tsx | 6 +- 13 files changed, 515 insertions(+), 864 deletions(-) delete mode 100644 src/components/AddEditRoleModal/index.tsx create mode 100644 src/pages/AddEditRolePage/index.tsx diff --git a/src/components/AddEditRoleModal/index.tsx b/src/components/AddEditRoleModal/index.tsx deleted file mode 100644 index 7b0206a..0000000 --- a/src/components/AddEditRoleModal/index.tsx +++ /dev/null @@ -1,300 +0,0 @@ -import React, { useEffect } from "react"; -import { - Box, - Button, - Checkbox, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - FormControl, - FormControlLabel, - FormHelperText, - FormLabel, - InputLabel, - MenuItem, - Select, - TextField, -} from "@mui/material"; -import CloseIcon from "@mui/icons-material/Close"; -import { useForm, Controller } from "react-hook-form"; - -interface AddRoleModalProps { - open: boolean; - handleClose: () => void; - handleCreate: (data: FormData) => void; - handleUpdate: ( - id: string, - name: string, - resource: { - moduleName: string; - moduleId: string; - permissions: string[]; - }[] - ) => void; - editRow: any; - data: { - resource: { - moduleName: string; - moduleId: string; - permissions: string[]; - }[]; - }; // Assuming `data` is passed as a prop -} - -interface FormData { - name: string; - resource: { - moduleName: string; - moduleId: string; - permissions: string[]; - }[]; -} - -const AddRoleModal: React.FC = ({ - open, - handleClose, - handleCreate, - handleUpdate, - editRow, - data, -}) => { - const { - control, - handleSubmit, - formState: { errors }, - setValue, - reset, - getValues, // Access getValues from the form methods here - } = useForm({ - defaultValues: { - name: "", - resource: [], // Ensure resource is initialized as an empty array - }, - }); - - - useEffect(() => { - if (editRow) { - setValue("name", editRow.name); - setValue("resource", editRow.resource); - } - }, [editRow, setValue]); - - // Handles permissions checkbox change for a specific resource - const handlePermissionChange = ( - resourceIndex: number, - permission: string, - checked: boolean - ) => { - const updatedResources = [...getValues().resource]; // Use getValues to get the current form values - const resource = updatedResources[resourceIndex]; - - if (checked) { - // Add permission if checked - resource.permissions = [ - ...new Set([...resource.permissions, permission]), - ]; - } else { - // Remove permission if unchecked - resource.permissions = resource.permissions.filter( - (p) => p !== permission - ); - } - - setValue("resource", updatedResources); // Update the resource field in form state - }; - - const onSubmit = (data: FormData) => { - if (editRow) { - handleUpdate(editRow.id, data.name, data.resource); - } else { - handleCreate(data); - } - - handleClose(); - reset(); - }; - - return ( - - - {editRow ? "Edit Role" : "Add Role"} - - - - - - - {/* Role Name Field */} - ( - - )} - /> - - {/* Resource Field */} - ( - - Resource - - - {errors.resource?.message} - - - )} - /> - - {/* Permissions Checkbox Fields for each resource */} - {getValues().resource && - getValues().resource.length > 0 && - getValues().resource.map((resource, resourceIndex) => ( - - - - {resource.moduleName} Permissions - - - handlePermissionChange( - resourceIndex, - "view", - e.target.checked - ) - } - /> - } - label="View" - /> - - handlePermissionChange( - resourceIndex, - "edit", - e.target.checked - ) - } - /> - } - label="Edit" - /> - - handlePermissionChange( - resourceIndex, - "delete", - e.target.checked - ) - } - /> - } - label="Delete" - /> - - { - errors.resource?.[resourceIndex] - ?.permissions?.message - } - - - - ))} - - - - - - - - ); -}; - -export default AddRoleModal; diff --git a/src/components/CustomTable/index.tsx b/src/components/CustomTable/index.tsx index 037e03d..40595af 100644 --- a/src/components/CustomTable/index.tsx +++ b/src/components/CustomTable/index.tsx @@ -73,7 +73,6 @@ const CustomTable: React.FC = ({ setViewModal, setModalOpen, }) => { - // console.log("columnsss", columns, rows) const dispatch = useDispatch(); const [anchorEl, setAnchorEl] = React.useState(null); const [selectedRow, setSelectedRow] = React.useState(null); @@ -112,56 +111,71 @@ const CustomTable: React.FC = ({ }; return ( - - - - - {columns.map((column) => ( - - {column.label} - - ))} - - - - {rows.map((row, rowIndex) => ( - + + +
+ + {columns.map((column) => ( - {isImage(row[column.id]) ? ( - Row - ) : column.id !== "action" ? ( - row[column.id] - ) : ( - { - handleClick(e, row); - setRowData(row); // Store the selected row - }} - > - - - )} + {column.label} ))} - - ))} - -
+ + + + {rows.map((row, rowIndex) => ( + + {columns.map((column) => ( + + {isImage(row[column.id]) ? ( + Row + ) : column.id !== "action" ? ( + row[column.id] + ) : ( + { + handleClick(e, row); + setRowData(row); // Store the selected row + }} + > + + + )} + + ))} + + ))} + + +
+ + {/* Menu Actions */} {open && ( = ({ )} - + ); }; diff --git a/src/components/LineChartCard/index.tsx b/src/components/LineChartCard/index.tsx index a8acfa0..8f73bcf 100644 --- a/src/components/LineChartCard/index.tsx +++ b/src/components/LineChartCard/index.tsx @@ -43,7 +43,7 @@ export default function LineChartCard() { return (
theme.spacing(2) }} > {data.map((card, index) => ( diff --git a/src/components/MenuContent/index.tsx b/src/components/MenuContent/index.tsx index 5d58f3c..794a33b 100644 --- a/src/components/MenuContent/index.tsx +++ b/src/components/MenuContent/index.tsx @@ -13,35 +13,10 @@ import { RootState } from "../../redux/store/store"; import DashboardOutlinedIcon from "@mui/icons-material/DashboardOutlined"; import ManageAccountsOutlinedIcon from "@mui/icons-material/ManageAccountsOutlined"; -const baseMenuItems = [ - { - text: "Dashboard", - icon: , - url: "/panel/dashboard", - }, - { - text: "Admins", - icon: , - url: "/panel/admin-list", - }, - { - text: "Users", - icon: , - url: "/panel/user-list", - }, - { - text: "Roles", - icon: , - url: "/panel/role-list", - }, -]; - //Eknoor singh and Jaanvi //date:- 12-Feb-2025 //Made a different variable for super admin to access all the details. - - type PropType = { hidden: boolean; }; @@ -51,24 +26,34 @@ export default function MenuContent({ hidden }: PropType) { const userRole = useSelector( (state: RootState) => state.profileReducer.user?.userType ); + const baseMenuItems = [ + { + text: "Dashboard", + icon: , + url: "/panel/dashboard", + }, + userRole === "superadmin" && { + text: "Admins", + icon: , + url: "/panel/admin-list", + }, + userRole === "admin" && { + text: "Users", + icon: , + url: "/panel/user-list", + }, + userRole === "superadmin" && { + text: "Roles", + icon: , + url: "/panel/role-list", + }, + ]; - - // const mainListItems = [ - // ...baseMenuItems, - // // ...(userRole === "superadmin" - // // ? [ - // // // { - // // // text: "Admin List", - // // // icon: , - // // // url: "/panel/admin-list", - // // // }, - // // ] - // // : []), - // ]; + const filteredMenuItems = baseMenuItems.filter(Boolean); return ( - {baseMenuItems.map((item, index) => ( + {filteredMenuItems.map((item, index) => ( diff --git a/src/components/SessionsChart/index.tsx b/src/components/SessionsChart/index.tsx index e47febc..d4cd487 100644 --- a/src/components/SessionsChart/index.tsx +++ b/src/components/SessionsChart/index.tsx @@ -11,9 +11,10 @@ export default function SessionsChart() { variant="outlined" sx={{ width: "100%", - height: "90%", + height: "100%", backgroundColor: "#202020", p: 2, + }} > diff --git a/src/components/barChartCard/index.tsx b/src/components/barChartCard/index.tsx index 80db70e..4138bf6 100644 --- a/src/components/barChartCard/index.tsx +++ b/src/components/barChartCard/index.tsx @@ -30,7 +30,7 @@ export default function RoundedBarChart() { return (
+ variant="h6" + align="left" + color="#FFFFFF" + sx={{ + fontFamily: "Gilroy", + fontWeight: 500, + fontSize: "18px", + lineHeight: "24px", + }} + > Charge Stats diff --git a/src/layouts/DashboardLayout/index.tsx b/src/layouts/DashboardLayout/index.tsx index 165d39e..6d2ad96 100644 --- a/src/layouts/DashboardLayout/index.tsx +++ b/src/layouts/DashboardLayout/index.tsx @@ -1,56 +1,72 @@ -// src/common/components/Layout - -import * as React from 'react'; -import { Box, Stack } from '@mui/material'; -import { Outlet } from 'react-router-dom'; -import SideMenu from '../../components/SideMenu'; -import AppNavbar from '../../components/AppNavbar'; -import Header from '../../components/Header'; -import AppTheme from '../../shared-theme/AppTheme'; +import * as React from "react"; +import { Box, Stack } from "@mui/material"; +import { Outlet } from "react-router-dom"; +import SideMenu from "../../components/SideMenu"; +import AppNavbar from "../../components/AppNavbar"; +import Header from "../../components/Header"; +import AppTheme from "../../shared-theme/AppTheme"; interface LayoutProps { - customStyles?: React.CSSProperties; + customStyles?: React.CSSProperties; } const DashboardLayout: React.FC = ({ customStyles }) => { - return ( - - - - - ({ - display: "flex", - height: '100vh', - flexGrow: 1, - backgroundColor: theme.vars - ? `rgba(${theme.vars.palette.background.defaultChannel} / 1)` - : theme.palette.background.default, - overflow: 'auto', - ...customStyles, - })} - > - + + {/* SideMenu - Responsive, shown only on large screens */} + + + - alignItems: 'center', - mx: 3, - pb: 5, - mt: { xs: 8, md: 0 }, - }} - > -
- - - - - - ); + {/* Navbar - Always visible */} + + + ({ + display: "flex", + flexDirection: "column", + height: "100vh", + flexGrow: 1, + backgroundColor: theme.vars + ? `rgba(${theme.vars.palette.background.defaultChannel} / 1)` + : theme.palette.background.default, + overflow: "auto", + ...customStyles, + mt: { xs: 8, md: 0 }, + })} + > + +
+ + + + + + ); }; export default DashboardLayout; diff --git a/src/pages/AddEditRolePage/index.tsx b/src/pages/AddEditRolePage/index.tsx new file mode 100644 index 0000000..acda76d --- /dev/null +++ b/src/pages/AddEditRolePage/index.tsx @@ -0,0 +1,283 @@ +import React, { useState } from "react"; +import { + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper, + Checkbox, + Typography, + Box, +} from "@mui/material"; + +// Define the data structure +interface Permission { + module: string; + list: boolean; + add: boolean; + edit: boolean; + view: boolean; + delete: boolean; +} + +// Sample data +const initialPermissions: Permission[] = [ + { + module: "Role And Permission", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Staff", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Manage Users", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Business Type", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Category", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Volumes", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Orders", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Discount", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Transactioned History", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Relaxable", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "State Contract", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Flag", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Contract Life", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Commission", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, + { + module: "Email Template", + list: false, + add: false, + edit: false, + view: false, + delete: false, + }, +]; + +// Table component +const AddEditRoleModal: React.FC = () => { + const [permissions, setPermissions] = + useState(initialPermissions); + + // Handle checkbox change + const handleCheckboxChange = (module: string, action: keyof Permission) => { + setPermissions((prevPermissions) => + prevPermissions.map((perm) => + perm.module === module + ? { ...perm, [action]: !perm[action] } + : perm + ) + ); + }; + + return ( + + + + {/* Role Row with space-evenly */} + + + Role + + Admin + + + + + {/* Header Row */} + + + Module Name + + + Actions + + + + + + {permissions.map((row, index) => ( + + {/* Module Name */} + {row.module} + + {/* Action Checkboxes */} + + + + handleCheckboxChange( + row.module, + "list" + ) + } + /> + + handleCheckboxChange( + row.module, + "add" + ) + } + /> + + handleCheckboxChange( + row.module, + "edit" + ) + } + /> + + handleCheckboxChange( + row.module, + "view" + ) + } + /> + + handleCheckboxChange( + row.module, + "delete" + ) + } + /> + + + + ))} + +
+
+ ); +}; + +export default AddEditRoleModal; diff --git a/src/pages/AdminList/index.tsx b/src/pages/AdminList/index.tsx index ccc620f..69aa05f 100644 --- a/src/pages/AdminList/index.tsx +++ b/src/pages/AdminList/index.tsx @@ -1,358 +1,3 @@ -// import { useEffect, useState } from "react"; -// import { -// Box, -// Button, -// Typography, -// TextField, -// InputAdornment, -// Paper, -// Table, -// TableBody, -// TableCell, -// TableContainer, -// TableHead, -// TableRow, -// Pagination, -// IconButton, -// } from "@mui/material"; -// import SearchIcon from "@mui/icons-material/Search"; -// import MoreHorizIcon from "@mui/icons-material/MoreHoriz"; -// import TuneIcon from "@mui/icons-material/Tune"; -// import { useDispatch, useSelector } from "react-redux"; -// import { adminList } from "../../redux/slices/adminSlice"; -// import { AppDispatch, RootState } from "../../redux/store/store"; - -// export default function AdminList() { -// const [searchQuery, setSearchQuery] = useState(""); -// const [currentPage, setCurrentPage] = useState(1); -// const adminsPerPage = 10; - -// const dispatch = useDispatch(); -// const admins = useSelector((state: RootState) => state.adminReducer.admins); - -// useEffect(() => { -// dispatch(adminList()); -// }, [dispatch]); - -// const staticAdmins = [ -// { -// name: "John Doe", -// location: "New York", -// managerAssigned: "Alice Johnson", -// vehicle: "Tesla Model S", -// phone: "+1 234 567 8901", -// }, -// { -// name: "Jane Smith", -// location: "Los Angeles", -// managerAssigned: "Bob Brown", -// vehicle: "Ford F-150", -// phone: "+1 987 654 3210", -// }, -// { -// name: "Michael Brown", -// location: "Chicago", -// managerAssigned: "Sarah Lee", -// vehicle: "Chevrolet Bolt", -// phone: "+1 312 555 7890", -// }, -// { -// name: "Emily Davis", -// location: "Houston", -// managerAssigned: "Tom Wilson", -// vehicle: "Nissan Leaf", -// phone: "+1 713 444 5678", -// }, -// { -// name: "Daniel Martinez", -// location: "Phoenix", -// managerAssigned: "Jessica White", -// vehicle: "BMW i3", -// phone: "+1 602 999 4321", -// }, -// { -// name: "Sophia Miller", -// location: "Philadelphia", -// managerAssigned: "Mark Adams", -// vehicle: "Audi e-tron", -// phone: "+1 215 777 6543", -// }, -// { -// name: "James Anderson", -// location: "San Antonio", -// managerAssigned: "Emma Thomas", -// vehicle: "Hyundai Kona EV", -// phone: "+1 210 321 8765", -// }, -// { -// name: "James Anderson", -// location: "San Antonio", -// managerAssigned: "Emma Thomas", -// vehicle: "Hyundai Kona EV", -// phone: "+1 210 321 8765", -// }, -// ]; - -// const adminData = admins.length ? admins : staticAdmins; - -// const filteredAdmins = adminData.filter((admin) => -// admin.name.toLowerCase().includes(searchQuery.toLowerCase()) -// ); - -// const indexOfLastAdmin = currentPage * adminsPerPage; -// const indexOfFirstAdmin = indexOfLastAdmin - adminsPerPage; -// const currentAdmins = filteredAdmins.slice( -// indexOfFirstAdmin, -// indexOfLastAdmin -// ); - -// const handlePageChange = (event, value) => { -// setCurrentPage(value); -// }; - -// return ( -// -// -// Charge stations -// - -// {/* Search & Buttons Section */} -// -// -// -// -// ), -// }} -// value={searchQuery} -// onChange={(e) => setSearchQuery(e.target.value)} -// /> -// -// -// - -// -// -// -// - -// {/* Table Section */} -// -// -// -// -// {[ -// "Name", -// "Location", -// "Manager Assigned", -// "Vehicle", -// "Phone Number", -// "Action", -// ].map((header) => ( -// -// {header} -// -// ))} -// -// -// -// {currentAdmins.map((admin, index) => ( -// -// -// {admin.name} -// -// -// {admin.location || "N/A"} -// -// -// {admin.managerAssigned || "N/A"} -// -// -// {admin.vehicle || "N/A"}{" "} -// -// +6 more -// -// -// -// {admin.phone} -// -// -// -// -// -// -// -// ))} -// -//
-//
- -// {/* Pagination */} -// -// -// Page Number : -// -// -// -//
-// ); -// } import React, { useEffect, useState } from "react"; import { Box, Button, Typography } from "@mui/material"; import AddEditCategoryModal from "../../components/AddEditCategoryModal"; @@ -467,25 +112,27 @@ export default function AdminList() { Admins - - {/* or - - - Don't have an account?{" "} - - Sign up - - - */} diff --git a/src/pages/RoleList/index.tsx b/src/pages/RoleList/index.tsx index 416d0b5..999df66 100644 --- a/src/pages/RoleList/index.tsx +++ b/src/pages/RoleList/index.tsx @@ -25,7 +25,7 @@ export default function RoleList() { const handleClickOpen = () => { setRowData(null); // Reset row data when opening for new role - setModalOpen(true); + setModalOpen(!modalOpen); }; const handleCloseModal = () => { @@ -126,12 +126,12 @@ export default function RoleList() { setRowData={setRowData} setModalOpen={setModalOpen} /> - + /> */} ); } From 4cf59e746f97244f384a344942b769e99ab155a8 Mon Sep 17 00:00:00 2001 From: jaanvi Date: Fri, 28 Feb 2025 10:13:17 +0530 Subject: [PATCH 2/4] mirror changes --- src/pages/AddEditRolePage/index.tsx | 281 +++++++++++++--------------- src/pages/RoleList/index.tsx | 251 +++++++++++++++++++------ src/router.tsx | 11 +- 3 files changed, 328 insertions(+), 215 deletions(-) diff --git a/src/pages/AddEditRolePage/index.tsx b/src/pages/AddEditRolePage/index.tsx index acda76d..8cb85ca 100644 --- a/src/pages/AddEditRolePage/index.tsx +++ b/src/pages/AddEditRolePage/index.tsx @@ -10,7 +10,11 @@ import { Checkbox, Typography, Box, + Grid, + FormControlLabel, + Button, } from "@mui/material"; +import { useNavigate } from "react-router-dom"; // Import useNavigate // Define the data structure interface Permission { @@ -25,7 +29,7 @@ interface Permission { // Sample data const initialPermissions: Permission[] = [ { - module: "Role And Permission", + module: "Role & Permission", list: false, add: false, edit: false, @@ -64,14 +68,6 @@ const initialPermissions: Permission[] = [ view: false, delete: false, }, - { - module: "Volumes", - list: false, - add: false, - edit: false, - view: false, - delete: false, - }, { module: "Orders", list: false, @@ -81,7 +77,7 @@ const initialPermissions: Permission[] = [ delete: false, }, { - module: "Discount", + module: "Discounts", list: false, add: false, edit: false, @@ -89,39 +85,7 @@ const initialPermissions: Permission[] = [ delete: false, }, { - module: "Transactioned History", - list: false, - add: false, - edit: false, - view: false, - delete: false, - }, - { - module: "Relaxable", - list: false, - add: false, - edit: false, - view: false, - delete: false, - }, - { - module: "State Contract", - list: false, - add: false, - edit: false, - view: false, - delete: false, - }, - { - module: "Flag", - list: false, - add: false, - edit: false, - view: false, - delete: false, - }, - { - module: "Contract Life", + module: "Transaction History", list: false, add: false, edit: false, @@ -137,7 +101,7 @@ const initialPermissions: Permission[] = [ delete: false, }, { - module: "Email Template", + module: "Email Templates", list: false, add: false, edit: false, @@ -147,9 +111,10 @@ const initialPermissions: Permission[] = [ ]; // Table component -const AddEditRoleModal: React.FC = () => { +const AddEditRolePage: React.FC = () => { const [permissions, setPermissions] = useState(initialPermissions); + const navigate = useNavigate(); // Initialize useNavigate // Handle checkbox change const handleCheckboxChange = (module: string, action: keyof Permission) => { @@ -162,122 +127,130 @@ const AddEditRoleModal: React.FC = () => { ); }; + // Handle Back Navigation + const handleBack = () => { + navigate("/panel/role-list"); // Navigate back to Role List + }; + return ( - - - - {/* Role Row with space-evenly */} - - - Role + {/* Title & Back Button Section */} + + + Role Permissions + + + + + {/* Table Container */} + +
+ {/* Table Head */} + + - Admin + Module Name - - - - {/* Header Row */} - - - Module Name - - - Actions - - - - - - {permissions.map((row, index) => ( - - {/* Module Name */} - {row.module} - - {/* Action Checkboxes */} - - - - handleCheckboxChange( - row.module, - "list" - ) - } - /> - - handleCheckboxChange( - row.module, - "add" - ) - } - /> - - handleCheckboxChange( - row.module, - "edit" - ) - } - /> - - handleCheckboxChange( - row.module, - "view" - ) - } - /> - - handleCheckboxChange( - row.module, - "delete" - ) - } - /> - + + Actions - ))} - -
-
+ + + {/* Table Body */} + + {permissions.map((row, index) => ( + + {/* Module Name */} + + {row.module} + + + {/* Action Checkboxes */} + + + {( + [ + "list", + "add", + "edit", + "view", + "delete", + ] as (keyof Permission)[] + ).map((action) => ( + + + handleCheckboxChange( + row.module, + action + ) + } + sx={{ + color: "#1976D2", + }} + /> + } + label={ + action + .charAt(0) + .toUpperCase() + + action.slice(1) + } + /> + + ))} + + + + ))} + + + + ); }; -export default AddEditRoleModal; +export default AddEditRolePage; diff --git a/src/pages/RoleList/index.tsx b/src/pages/RoleList/index.tsx index 999df66..0639790 100644 --- a/src/pages/RoleList/index.tsx +++ b/src/pages/RoleList/index.tsx @@ -1,11 +1,151 @@ +// import React, { useEffect, useState } from "react"; +// import { Box, Button, Typography } from "@mui/material"; +// import AddEditRoleModal from "../../components/AddEditRoleModal"; +// import { useForm } from "react-hook-form"; +// import CustomTable, { Column } from "../../components/CustomTable"; +// import { useDispatch, useSelector } from "react-redux"; +// import { createRole, roleList } from "../../redux/slices/roleSlice"; +// import { AppDispatch, RootState } from "../../redux/store/store"; + +// export default function RoleList() { +// const [modalOpen, setModalOpen] = useState(false); +// const { reset } = useForm(); + +// const [deleteModal, setDeleteModal] = React.useState(false); +// const [viewModal, setViewModal] = React.useState(false); +// const [rowData, setRowData] = React.useState(null); + +// const dispatch = useDispatch(); + +// const roles = useSelector((state: RootState) => state.roleReducer.roles); + +// useEffect(() => { +// dispatch(roleList()); +// }, [dispatch]); + +// const handleClickOpen = () => { +// setRowData(null); // Reset row data when opening for new role +// setModalOpen(!modalOpen); +// }; + +// const handleCloseModal = () => { +// setModalOpen(false); +// setRowData(null); +// reset(); +// }; + +// const handleCreate = async (data: { +// name: string; +// resource: { +// moduleName: string; +// moduleId: string; +// permissions: string[]; +// }[]; +// }) => { +// try { +// await dispatch(createRole(data)); +// await dispatch(roleList()); // Refresh the list after creation +// handleCloseModal(); +// } catch (error) { +// console.error("Creation failed", error); +// } +// }; + +// const categoryColumns: Column[] = [ +// { id: "srno", label: "Sr No" }, +// { id: "name", label: "Name" }, +// { id: "action", label: "Action", align: "center" }, +// ]; + +// const categoryRows = roles?.length +// ? roles?.map(function ( +// role: { +// id: string; +// name: string; +// // email: string; + +// // phone: string; +// // location?: string; +// // managerAssigned?: string; +// // vehicle?: string; +// }, +// index: number +// ) { +// return { +// id: role?.id, +// srno: index + 1, +// name: role?.name, +// // email: user?.email, +// // phone: user?.phone, +// // location: user?.location, +// // managerAssigned: user?.managerAssigned, +// // vehicle: user?.vehicle, +// }; +// }) +// : []; + +// console.log("Category Rows:", categoryRows); + +// return ( +// <> +// +// +// Roles +// +// +// + +// +// {/* */} +// +// ); +// } import React, { useEffect, useState } from "react"; -import { Box, Button, Typography } from "@mui/material"; +import { Box, Button, Typography, TextField, Chip } from "@mui/material"; import AddEditRoleModal from "../../components/AddEditRoleModal"; +import PermissionsTable from "../../pages/PermissionTable"; import { useForm } from "react-hook-form"; import CustomTable, { Column } from "../../components/CustomTable"; import { useDispatch, useSelector } from "react-redux"; import { createRole, roleList } from "../../redux/slices/roleSlice"; import { AppDispatch, RootState } from "../../redux/store/store"; +import { useNavigate } from "react-router-dom"; +import AddEditRolePage from "../AddEditRolePage"; export default function RoleList() { const [modalOpen, setModalOpen] = useState(false); @@ -14,8 +154,11 @@ export default function RoleList() { const [deleteModal, setDeleteModal] = React.useState(false); const [viewModal, setViewModal] = React.useState(false); const [rowData, setRowData] = React.useState(null); + const [searchTerm, setSearchTerm] = useState(""); + const [showPermissions, setShowPermissions] = useState(false); const dispatch = useDispatch(); + const navigate = useNavigate(); const roles = useSelector((state: RootState) => state.roleReducer.roles); @@ -24,8 +167,7 @@ export default function RoleList() { }, [dispatch]); const handleClickOpen = () => { - setRowData(null); // Reset row data when opening for new role - setModalOpen(!modalOpen); + navigate("/panel/permissions"); // Navigate to the correct route }; const handleCloseModal = () => { @@ -54,35 +196,28 @@ export default function RoleList() { const categoryColumns: Column[] = [ { id: "srno", label: "Sr No" }, { id: "name", label: "Name" }, + { id: "status", label: "Status" }, { id: "action", label: "Action", align: "center" }, ]; - const categoryRows = roles?.length - ? roles?.map(function ( - role: { - id: string; - name: string; - // email: string; - - // phone: string; - // location?: string; - // managerAssigned?: string; - // vehicle?: string; - }, - index: number - ) { - return { - id: role?.id, - srno: index + 1, - name: role?.name, - // email: user?.email, - // phone: user?.phone, - // location: user?.location, - // managerAssigned: user?.managerAssigned, - // vehicle: user?.vehicle, - }; - }) - : []; + const categoryRows = roles?.map((role: Role, index: number) => ({ + id: role.id, + srno: index + 1, + name: role.name, + status: ( + + ), + })); console.log("Category Rows:", categoryRows); @@ -91,47 +226,43 @@ export default function RoleList() { - - Roles - + setSearchTerm(e.target.value)} + sx={{ width: "30%" }} + /> - - {/* */} + {showPermissions ? ( + + ) : ( + + )} ); } diff --git a/src/router.tsx b/src/router.tsx index f7af3de..f8fc85d 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -3,6 +3,7 @@ import React, { lazy, Suspense } from "react"; import LoadingComponent from "./components/Loading"; import DashboardLayout from "./layouts/DashboardLayout"; import RoleList from "./pages/RoleList"; +import AddEditRolePage from "./pages/AddEditRolePage"; // Page imports const Login = lazy(() => import("./pages/Auth/Login")); @@ -93,7 +94,15 @@ export default function AppRouter() { /> } /> - + } + /> + } + /> Date: Fri, 28 Feb 2025 16:24:40 +0530 Subject: [PATCH 3/4] create active disactive feature --- src/components/AddEditCategoryModal/index.tsx | 4 +- src/components/CustomTable/index.tsx | 224 +++++++++++++----- src/pages/ProfilePage/index.tsx | 6 +- src/pages/RoleList/index.tsx | 151 +----------- src/redux/slices/roleSlice.ts | 98 +++++--- 5 files changed, 251 insertions(+), 232 deletions(-) diff --git a/src/components/AddEditCategoryModal/index.tsx b/src/components/AddEditCategoryModal/index.tsx index ecf4fa9..2033bbc 100644 --- a/src/components/AddEditCategoryModal/index.tsx +++ b/src/components/AddEditCategoryModal/index.tsx @@ -172,7 +172,7 @@ const AddEditCategoryModal: React.FC = ({ /> )} /> - = ({ helperText={errors.password?.message} /> )} - /> + />} ({ [`&.${tableCellClasses.head}`]: { backgroundColor: " #1565c0", @@ -38,22 +50,19 @@ export interface Column { interface Row { [key: string]: any; - status: number; - statusValue: any; } interface CustomTableProps { columns: Column[]; rows: Row[]; setDeleteModal: Function; - // setRowData: Function; - // setModalOpen: Function; + setRowData: Function; + setModalOpen: Function; viewModal: boolean; setViewModal: Function; deleteModal: boolean; - setRowData: React.Dispatch>; // Adjust this type if needed - setModalOpen: React.Dispatch>; handleStatusToggle: (id: string, currentStatus: number) => void; + tableType?: string; } const CustomTable: React.FC = ({ @@ -66,27 +75,54 @@ const CustomTable: React.FC = ({ setViewModal, setModalOpen, handleStatusToggle, + tableType, }) => { + const dispatch = useDispatch(); const [anchorEl, setAnchorEl] = React.useState(null); const [selectedRow, setSelectedRow] = React.useState(null); const open = Boolean(anchorEl); - ///const dispatch = useDispatch(); // Initialize dispatch - // Handle menu actions const handleClick = (event: React.MouseEvent, row: Row) => { setAnchorEl(event.currentTarget); - setSelectedRow(row); + setSelectedRow(row); // Ensure the row data is set + setRowData(row); }; const handleClose = () => { setAnchorEl(null); }; - const dispatch = useDispatch(); - // Handle status toggle logic - // const handleStatusToggle = (id: string, status: number) => { - // dispatch(toggleStatus({ id, status })); // Dispatch the action to update status - // }; + + 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); + + dispatch(deleteAdmin(id || "")); + setDeleteModal(false); // Close the modal only after deletion + handleClose(); + }; + + const handleViewButton = (id: string | undefined) => { + if (!id) console.error("ID not found", id); + + dispatch(adminList()); + setViewModal(false); + }; + + const handleToggleStatus = () => { + if (selectedRow) { + // Toggle the opposite of current status + const newStatus = selectedRow.statusValue === 1 ? 0 : 1; + handleStatusToggle(selectedRow.id, newStatus); + } + handleClose(); + }; return ( @@ -97,7 +133,11 @@ const CustomTable: React.FC = ({ {columns.map((column) => ( {column.label} @@ -110,15 +150,33 @@ const CustomTable: React.FC = ({ {columns.map((column) => ( - {column.id !== "action" ? ( + {isImage(row[column.id]) ? ( + Row + ) : column.id !== "action" ? ( row[column.id] ) : ( - handleClick(e, row) - } + onClick={(e) => { + handleClick(e, row); + setRowData(row); // Store the selected row + }} > @@ -132,46 +190,106 @@ const CustomTable: React.FC = ({ {/* Menu Actions */} - {open && selectedRow && ( + {open && ( - - - {/* This button now toggles the status based on the current status */} - + + {viewModal && ( + + handleViewButton(selectedRow?.id) + } + open={viewModal} + setViewModal={setViewModal} + id={selectedRow?.id} + /> + )} + - + {tableType === "roleList" && ( + + )} + + + {deleteModal && ( + + handleDeleteButton(selectedRow?.id) + } + open={deleteModal} + setDeleteModal={setDeleteModal} + id={selectedRow?.id} + /> + )} + )} diff --git a/src/pages/ProfilePage/index.tsx b/src/pages/ProfilePage/index.tsx index 86488a8..1bebb78 100644 --- a/src/pages/ProfilePage/index.tsx +++ b/src/pages/ProfilePage/index.tsx @@ -56,9 +56,7 @@ const ProfilePage = () => { { Phone: {user?.phone || "N/A"} - Role: {user?.role || "N/A"} + Role: {user?.userType || "N/A"} diff --git a/src/pages/RoleList/index.tsx b/src/pages/RoleList/index.tsx index 0feeb32..58344bf 100644 --- a/src/pages/RoleList/index.tsx +++ b/src/pages/RoleList/index.tsx @@ -43,6 +43,10 @@ export default function RoleList() { reset(); }; + const handleStatusToggle = (id: string, newStatus: number) => { + dispatch(toggleStatus({ id, status: newStatus })); + }; + const handleCreate = async (data: { name: string; resource: { @@ -120,158 +124,17 @@ export default function RoleList() { ) : ( { - // Correct logic to toggle between active and inactive - const updatedStatus = currentStatus === 1 ? 0 : 1; - dispatch(toggleStatus({ id, status: updatedStatus })); - }} + handleStatusToggle={handleStatusToggle} + tableType="roleList" /> )} ); } - -// import React, { useEffect, useState } from "react"; -// import { Box, Button, Typography } from "@mui/material"; -// import AddEditRoleModal from "../../components/AddEditRoleModal"; -// import { useForm } from "react-hook-form"; -// import CustomTable, { Column } from "../../components/CustomTable"; -// import { useDispatch, useSelector } from "react-redux"; -// import { createRole, roleList } from "../../redux/slices/roleSlice"; -// import { AppDispatch, RootState } from "../../redux/store/store"; - -// export default function RoleList() { -// const [modalOpen, setModalOpen] = useState(false); -// const { reset } = useForm(); - -// const [deleteModal, setDeleteModal] = React.useState(false); -// const [viewModal, setViewModal] = React.useState(false); -// const [rowData, setRowData] = React.useState(null); - -// const dispatch = useDispatch(); - -// const roles = useSelector((state: RootState) => state.roleReducer.roles); - -// useEffect(() => { -// dispatch(roleList()); -// }, [dispatch]); - -// const handleClickOpen = () => { -// setRowData(null); // Reset row data when opening for new role -// setModalOpen(!modalOpen); -// }; - -// const handleCloseModal = () => { -// setModalOpen(false); -// setRowData(null); -// reset(); -// }; - -// const handleCreate = async (data: { -// name: string; -// resource: { -// moduleName: string; -// moduleId: string; -// permissions: string[]; -// }[]; -// }) => { -// try { -// await dispatch(createRole(data)); -// await dispatch(roleList()); // Refresh the list after creation -// handleCloseModal(); -// } catch (error) { -// console.error("Creation failed", error); -// } -// }; - -// const categoryColumns: Column[] = [ -// { id: "srno", label: "Sr No" }, -// { id: "name", label: "Name" }, -// { id: "action", label: "Action", align: "center" }, -// ]; - -// const categoryRows = roles?.length -// ? roles?.map(function ( -// role: { -// id: string; -// name: string; -// // email: string; - -// // phone: string; -// // location?: string; -// // managerAssigned?: string; -// // vehicle?: string; -// }, -// index: number -// ) { -// return { -// id: role?.id, -// srno: index + 1, -// name: role?.name, -// // email: user?.email, -// // phone: user?.phone, -// // location: user?.location, -// // managerAssigned: user?.managerAssigned, -// // vehicle: user?.vehicle, -// }; -// }) -// : []; - -// console.log("Category Rows:", categoryRows); - -// return ( -// <> -// -// -// Roles -// -// -// - -// -// {/* */} -// -// ); -// } diff --git a/src/redux/slices/roleSlice.ts b/src/redux/slices/roleSlice.ts index 797014c..9c20808 100644 --- a/src/redux/slices/roleSlice.ts +++ b/src/redux/slices/roleSlice.ts @@ -5,7 +5,7 @@ import { toast } from "sonner"; // Define TypeScript types interface Role { - id: any; + id: string; name: string; resource: { moduleName: string; @@ -28,7 +28,7 @@ const initialState: RoleState = { error: null, }; -export const roleList = createAsyncThunk( +export const roleList = createAsyncThunk( "fetchRoles", async (_, { rejectWithValue }) => { try { @@ -37,11 +37,12 @@ export const roleList = createAsyncThunk( const response = await http.get("get"); - if (!response.data?.data) throw new Error("Invalid API response"); + if (!response.data) throw new Error("Invalid API response"); - return response.data.data; + // Return the full response to handle in the reducer + return response.data; } catch (error: any) { - toast.error("Error Fetching Roles" + error); + toast.error("Error Fetching Roles: " + error.message); return rejectWithValue( error?.response?.data?.message || "An error occurred" ); @@ -51,7 +52,7 @@ export const roleList = createAsyncThunk( // Create Role export const createRole = createAsyncThunk< - Role, + any, { name: string; resource: { @@ -61,11 +62,16 @@ export const createRole = createAsyncThunk< }[]; }, { rejectValue: string } ->("/CreateRole", async (data, { rejectWithValue }) => { +>("role/createRole", async (data, { rejectWithValue }) => { try { const response = await http.post("create", data); + toast.success("Role created successfully"); return response.data; } catch (error: any) { + toast.error( + "Failed to create role: " + + (error.response?.data?.message || "Unknown error") + ); return rejectWithValue( error.response?.data?.message || "An error occurred" ); @@ -73,23 +79,40 @@ export const createRole = createAsyncThunk< }); export const toggleStatus = createAsyncThunk< - Role, - { id: string; status: number }, // status now expects a number (0 or 1) + any, + { id: string; status: number }, { rejectValue: string } ->("/toggleRoleStatus", async ({ id, status }, { rejectWithValue }) => { +>("role/toggleStatus", async ({ id, status }, { rejectWithValue }) => { try { const response = await http.patch(`${id}`, { status }); - console.log("API Response:", response.data); - return response.data; + + if (response.data.statusCode === 200) { + toast.success( + response.data.message || "Status updated successfully" + ); + // Return both the response data and the requested status for reliable state updates + return { + responseData: response.data, + id, + status, + }; + } else { + throw new Error(response.data.message || "Failed to update status"); + } } catch (error: any) { + toast.error( + "Error updating status: " + (error.message || "Unknown error") + ); return rejectWithValue( - error.response?.data?.message || "An error occurred" + error.response?.data?.message || + error.message || + "An error occurred" ); } }); const roleSlice = createSlice({ - name: "fetchRoles", + name: "roles", initialState, reducers: {}, extraReducers: (builder) => { @@ -102,7 +125,11 @@ const roleSlice = createSlice({ roleList.fulfilled, (state, action: PayloadAction) => { state.loading = false; - state.roles = action.payload.results; // Extract results from response + // Properly extract roles from the response data structure + state.roles = + action.payload.data?.results || + action.payload.data || + []; } ) .addCase(roleList.rejected, (state, action) => { @@ -114,9 +141,12 @@ const roleSlice = createSlice({ }) .addCase( createRole.fulfilled, - (state, action: PayloadAction) => { + (state, action: PayloadAction) => { state.loading = false; - state.roles.push(action.payload); + // Add the newly created role to the state if it exists in the response + if (action.payload.data) { + state.roles.push(action.payload.data); + } } ) .addCase( @@ -126,27 +156,37 @@ const roleSlice = createSlice({ state.error = action.payload || "Failed to create role"; } ) + .addCase(toggleStatus.pending, (state) => { + state.loading = true; + }) .addCase( toggleStatus.fulfilled, - (state, action: PayloadAction) => { + (state, action: PayloadAction) => { state.loading = false; - const updatedRole = action.payload; - const index = state.roles.findIndex( - (role) => role.id === updatedRole.id + // Get the id and updated status from the action payload + const { id, status } = action.payload; + + // Find and update the role with the new status + const roleIndex = state.roles.findIndex( + (role) => role.id === id ); - if (index >= 0) { - state.roles[index] = { - ...state.roles[index], - status: updatedRole.status, + if (roleIndex !== -1) { + state.roles[roleIndex] = { + ...state.roles[roleIndex], + status: status, }; } } ) - .addCase(toggleStatus.rejected, (state, action) => { - state.loading = false; - state.error = action.payload || "Failed to toggle role status"; - }); + .addCase( + toggleStatus.rejected, + (state, action: PayloadAction) => { + state.loading = false; + state.error = + action.payload || "Failed to toggle role status"; + } + ); }, }); From d21f4f5d2765672d696a5486cb23078c84daa26e Mon Sep 17 00:00:00 2001 From: jaanvi Date: Mon, 3 Mar 2025 13:36:37 +0530 Subject: [PATCH 4/4] add functionality to search and password visibility and responsivess added in somepage --- src/components/AddEditCategoryModal/index.tsx | 76 ++++++++++++++----- src/components/AppNavbar/index.tsx | 2 +- src/components/CustomTable/index.tsx | 25 ++++-- src/components/Header/index.tsx | 35 +++++++-- src/pages/AddEditRolePage/index.tsx | 10 ++- src/pages/AdminList/index.tsx | 57 +++++++++++--- src/pages/Auth/Login/index.tsx | 1 - src/pages/RoleList/index.tsx | 64 +++++++++++----- 8 files changed, 199 insertions(+), 71 deletions(-) diff --git a/src/components/AddEditCategoryModal/index.tsx b/src/components/AddEditCategoryModal/index.tsx index 2033bbc..521bbba 100644 --- a/src/components/AddEditCategoryModal/index.tsx +++ b/src/components/AddEditCategoryModal/index.tsx @@ -6,10 +6,12 @@ import { DialogActions, DialogContent, DialogTitle, + IconButton, TextField, } from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; import { useForm, Controller } from "react-hook-form"; +import { Visibility, VisibilityOff } from "@mui/icons-material"; //By Jaanvi : Edit Model :: 11-feb-25 interface AddEditCategoryModalProps { @@ -86,6 +88,8 @@ const AddEditCategoryModal: React.FC = ({ } }, [editRow, setValue, reset]); + const [showPassword, setShowPassword] = React.useState(false); + return ( = ({ /> )} /> - {!editRow && ( - - )} - />} + {!editRow && ( + ( + <> + + + + setShowPassword((prev) => !prev) + } + > + {showPassword ? ( + + ) : ( + + )} + + + + )} + /> + )} - + {/* */} diff --git a/src/components/CustomTable/index.tsx b/src/components/CustomTable/index.tsx index e995eca..4927964 100644 --- a/src/components/CustomTable/index.tsx +++ b/src/components/CustomTable/index.tsx @@ -127,7 +127,14 @@ const CustomTable: React.FC = ({ return ( - +
{columns.map((column) => ( @@ -136,7 +143,13 @@ const CustomTable: React.FC = ({ align={column.align || "left"} sx={{ whiteSpace: "nowrap", // Prevent wrapping - fontSize: { xs: "12px", sm: "14px" }, // Responsively adjust font size + // fontSize: { xs: "12px", sm: "14px" }, + fontSize: { + xs: "10px", + sm: "12px", + md: "14px", + }, // Adjust font size responsively + padding: { xs: "8px", sm: "12px" }, }} > {column.label} @@ -154,9 +167,11 @@ const CustomTable: React.FC = ({ sx={{ whiteSpace: "nowrap", // Prevent wrapping fontSize: { - xs: "12px", - sm: "14px", - }, // Responsively adjust font size + xs: "10px", + sm: "12px", + md: "14px", + }, // Adjust font size responsively + padding: { xs: "8px", sm: "12px" }, }} > {isImage(row[column.id]) ? ( diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 563cea5..4c3f027 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -12,10 +12,10 @@ import ColorModeIconDropdown from "../../shared-theme/ColorModeIconDropdown"; import NotificationsRoundedIcon from "@mui/icons-material/NotificationsRounded"; export default function Header() { - const [showNotifications, setShowNotifications] = React.useState(false); - const toggleNotifications = () => { - setShowNotifications((prev) => !prev); - }; + const [showNotifications, setShowNotifications] = React.useState(false); + const toggleNotifications = () => { + setShowNotifications((prev) => !prev); + }; return ( @@ -35,11 +36,16 @@ export default function Header() { spacing={3} alignItems="center" justifyContent="flex-end" + sx={{ + width: "100%", + justifyContent: { xs: "center", sm: "flex-end" }, + marginTop: { xs: 2, sm: 0 }, + }} > {/* Search Bar */} {/* Notification and Profile Section */} - + {/* Custom Bell Icon */} {/* diff --git a/src/pages/AddEditRolePage/index.tsx b/src/pages/AddEditRolePage/index.tsx index 65bd82d..3ee8144 100644 --- a/src/pages/AddEditRolePage/index.tsx +++ b/src/pages/AddEditRolePage/index.tsx @@ -157,14 +157,17 @@ const AddEditRolePage: React.FC = () => { {/* Role Name Input */} - + + @@ -270,7 +273,6 @@ const AddEditRolePage: React.FC = () => { autoHideDuration={3000} onClose={() => setOpenSnackbar(false)} message="Role added successfully!" - /> ); diff --git a/src/pages/AdminList/index.tsx b/src/pages/AdminList/index.tsx index f554794..f579f75 100644 --- a/src/pages/AdminList/index.tsx +++ b/src/pages/AdminList/index.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useState } from "react"; -import { Box, Button, Typography } from "@mui/material"; +import { Box, Button, TextField, Typography } from "@mui/material"; import AddEditCategoryModal from "../../components/AddEditCategoryModal"; import { useForm } from "react-hook-form"; import CustomTable, { Column } from "../../components/CustomTable"; @@ -10,6 +10,7 @@ import { createAdmin, } from "../../redux/slices/adminSlice"; import { AppDispatch, RootState } from "../../redux/store/store"; +import SearchIcon from "@mui/icons-material/Search"; export default function AdminList() { const [modalOpen, setModalOpen] = useState(false); @@ -22,7 +23,7 @@ export default function AdminList() { const dispatch = useDispatch(); const admins = useSelector((state: RootState) => state.adminReducer.admins); - + const [searchTerm, setSearchTerm] = useState(""); useEffect(() => { dispatch(adminList()); }, [dispatch]); @@ -84,9 +85,18 @@ export default function AdminList() { { id: "registeredAddress", label: "Address" }, { id: "action", label: "Action", align: "center" }, ]; + const filteredAdmins = admins?.filter( + (admin) => + admin.name.toLowerCase().includes(searchTerm.toLowerCase()) || + admin.email.toLowerCase().includes(searchTerm.toLowerCase()) || + admin.phone.toLowerCase().includes(searchTerm.toLowerCase()) || + admin.registeredAddress + .toLowerCase() + .includes(searchTerm.toLowerCase()) + ); - const categoryRows = admins?.length - ? admins?.map( + const categoryRows = filteredAdmins?.length + ? filteredAdmins?.map( ( admin: { id: string; @@ -109,6 +119,19 @@ export default function AdminList() { return ( <> + + Admins + + - - Admins - + setSearchTerm(e.target.value)} + sx={{ + width: { xs: "100%", sm: "30%" }, + marginBottom: { xs: 2, sm: 0 }, + }} + InputProps={{ + startAdornment: ( + + ), + }} + /> +