diff --git a/public/Bell.jpg b/public/Bell.jpg
new file mode 100644
index 0000000..a5c21ac
Binary files /dev/null and b/public/Bell.jpg differ
diff --git a/public/avatar.png b/public/avatar.png
new file mode 100644
index 0000000..8c87604
Binary files /dev/null and b/public/avatar.png differ
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx
index 4724de2..46ab0ad 100644
--- a/src/components/Header/index.tsx
+++ b/src/components/Header/index.tsx
@@ -1,63 +1,89 @@
import * as React from "react";
import Stack from "@mui/material/Stack";
-import NotificationsRoundedIcon from "@mui/icons-material/NotificationsRounded";
-import CustomDatePicker from "../CustomDatePicker";
-import NavbarBreadcrumbs from "../NavbarBreadcrumbs";
-import MenuButton from "../MenuButton";
-import ColorModeIconDropdown from "../../shared-theme/ColorModeIconDropdown";
+import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
-import Search from "../Search";
+import InputBase from "@mui/material/InputBase";
+import SearchIcon from "@mui/icons-material/Search";
+import Divider from "@mui/material/Divider";
+import MenuButton from "../MenuButton";
+import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
export default function Header() {
const [showNotifications, setShowNotifications] = React.useState(false);
const toggleNotifications = () => {
setShowNotifications((prev) => !prev);
};
+
return (
-
-
-
-
-
-
-
-
-
-
- {showNotifications && (
+
+
+ {/* Search Bar */}
-
- No notifications yet
-
+
+
- )}
-
+
+ {/* Notification and Profile Section */}
+
+
+ {/* Custom Bell Icon */}
+
+
+
+
+
+
+ Momah
+
+ {/* Dropdown Icon */}
+
+
+
+
+
);
}
diff --git a/src/components/MenuContent/index.tsx b/src/components/MenuContent/index.tsx
index 7b91f6a..cc6c53b 100644
--- a/src/components/MenuContent/index.tsx
+++ b/src/components/MenuContent/index.tsx
@@ -22,7 +22,11 @@ const baseMenuItems = [
icon: ,
url: "/panel/admin-list",
},
-
+ {
+ text: "Users",
+ icon: ,
+ url: "/panel/user-list",
+ },
];
//Eknoor singh and Jaanvi
diff --git a/src/pages/AdminList/index.tsx b/src/pages/AdminList/index.tsx
index 0cb75cf..e095411 100644
--- a/src/pages/AdminList/index.tsx
+++ b/src/pages/AdminList/index.tsx
@@ -1,159 +1,355 @@
-import React, { useEffect, useState } from "react";
-import { Box, Button, Typography } from "@mui/material";
-import AddEditCategoryModal from "../../components/AddEditCategoryModal";
-import { useForm } from "react-hook-form";
-import CustomTable, { Column } from "../../components/CustomTable";
-import { useDispatch, useSelector } from "react-redux";
+import { useEffect, useState } from "react";
import {
- adminList,
- updateAdmin,
- createAdmin,
-} from "../../redux/slices/adminSlice";
+ 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 [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 [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 handleClickOpen = () => {
- setRowData(null); // Reset row data when opening for new admin
- setModalOpen(true);
- };
-
- const handleCloseModal = () => {
- setModalOpen(false);
- setRowData(null);
- reset();
- };
-
- const handleCreate = async (data: {
- name: string;
- email: string;
- phone: string;
- registeredAddress: string;
- }) => {
- try {
- await dispatch(createAdmin(data));
- await dispatch(adminList()); // Refresh the list after creation
- handleCloseModal();
- } catch (error) {
- console.error("Creation failed", error);
- }
- };
-
- const handleUpdate = async (
- id: string,
- name: string,
- email: string,
- phone: string,
- registeredAddress: string
- ) => {
- try {
- await dispatch(
- updateAdmin({
- id,
- name,
- email,
- phone,
- registeredAddress,
- })
- );
- await dispatch(adminList());
- } catch (error) {
- console.error("Update failed", error);
- }
- };
-
- const categoryColumns: Column[] = [
- { id: "srno", label: "Sr No" },
- { id: "name", label: "Name" },
- { id: "email", label: "Email" },
- { id: "phone", label: "Phone" },
- { id: "registeredAddress", label: "Address" },
- { id: "action", label: "Action", align: "center" },
+ 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 categoryRows = admins?.length
- ? admins?.map(
- (
- admin: {
- id: string;
- name: string;
- email: string;
- phone: string;
- registeredAddress: string;
- },
- index: number
- ) => ({
- id: admin?.id,
- srno: index + 1,
- name: admin?.name,
- email: admin?.email,
- phone: admin?.phone,
- registeredAddress: admin?.registeredAddress,
- })
- )
- : [];
+ 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 */}
+
- Admins
+ Page Number :
-
+
-
-
-
- >
+
);
}
diff --git a/src/pages/UserList/index.tsx b/src/pages/UserList/index.tsx
new file mode 100644
index 0000000..bddda89
--- /dev/null
+++ b/src/pages/UserList/index.tsx
@@ -0,0 +1,313 @@
+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 { userList } from "../../redux/slices/userSlice"; // Make sure userSlice exists
+import { AppDispatch, RootState } from "../../redux/store/store";
+
+export default function UserList() {
+ const [searchQuery, setSearchQuery] = useState("");
+ const [currentPage, setCurrentPage] = useState(1);
+ const usersPerPage = 10;
+
+ const dispatch = useDispatch();
+ const users = useSelector((state: RootState) => state.userReducer.users);
+
+ useEffect(() => {
+ dispatch(userList());
+ }, [dispatch]);
+
+ const staticUsers = [
+ {
+ name: "Alice Johnson",
+ email: "alice@example.com",
+ role: "User",
+ phone: "+1 234 567 8901",
+ },
+ {
+ name: "Bob Brown",
+ email: "bob@example.com",
+ role: "Admin",
+ phone: "+1 987 654 3210",
+ },
+ {
+ name: "Charlie Davis",
+ email: "charlie@example.com",
+ role: "User",
+ phone: "+1 312 555 7890",
+ },
+ {
+ name: "Alice Johnson",
+ email: "alice@example.com",
+ role: "User",
+ phone: "+1 234 567 8901",
+ },
+ {
+ name: "Bob Brown",
+ email: "bob@example.com",
+ role: "Admin",
+ phone: "+1 987 654 3210",
+ },
+ {
+ name: "Charlie Davis",
+ email: "charlie@example.com",
+ role: "User",
+ phone: "+1 312 555 7890",
+ },
+ {
+ name: "Bob Brown",
+ email: "bob@example.com",
+ role: "Admin",
+ phone: "+1 987 654 3210",
+ },
+ {
+ name: "Charlie Davis",
+ email: "charlie@example.com",
+ role: "User",
+ phone: "+1 312 555 7890",
+ },
+ ];
+
+ const userData = users.length ? users : staticUsers;
+
+ const filteredUsers = userData.filter((user) =>
+ user.name.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ const indexOfLastUser = currentPage * usersPerPage;
+ const indexOfFirstUser = indexOfLastUser - usersPerPage;
+ const currentUsers = filteredUsers.slice(indexOfFirstUser, indexOfLastUser);
+
+ const handlePageChange = (event, value) => {
+ setCurrentPage(value);
+ };
+
+ return (
+
+
+ User List
+
+
+ {/* Search & Buttons Section */}
+
+
+
+
+ ),
+ }}
+ value={searchQuery}
+ onChange={(e) => setSearchQuery(e.target.value)}
+ />
+
+
+
+
+
+
+
+
+
+ {/* Table Section */}
+
+
+
+
+ {["Name", "Email", "Role", "Phone", "Action"].map(
+ (header) => (
+
+ {header}
+
+ )
+ )}
+
+
+
+ {currentUsers.map((user, index) => (
+
+
+ {user.name}
+
+
+ {user.email}
+
+
+ {user.role}
+
+
+ {user.phone}
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ {/* Pagination */}
+
+
+ Page Number :
+
+
+
+
+ );
+}
diff --git a/src/redux/reducers.ts b/src/redux/reducers.ts
index 03caa21..4ad7387 100644
--- a/src/redux/reducers.ts
+++ b/src/redux/reducers.ts
@@ -3,11 +3,13 @@ import { combineReducers } from "@reduxjs/toolkit";
import authReducer from "./slices/authSlice";
import adminReducer from "./slices/adminSlice";
import profileReducer from "./slices/profileSlice";
+import userReducer from "./slices/userSlice.ts";
const rootReducer = combineReducers({
authReducer,
adminReducer,
- profileReducer
+ profileReducer,
+ userReducer,
});
export type RootState = ReturnType;
diff --git a/src/redux/slices/userSlice.ts b/src/redux/slices/userSlice.ts
new file mode 100644
index 0000000..d9242fd
--- /dev/null
+++ b/src/redux/slices/userSlice.ts
@@ -0,0 +1,59 @@
+import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
+import axios from "axios";
+
+// Define TypeScript types
+interface User {
+ id: number;
+ name: string;
+ email: string;
+ phone?: string;
+ location?: string;
+ managerAssigned?: string;
+ vehicle?: string;
+}
+
+interface UserState {
+ users: User[];
+ loading: boolean;
+ error: string | null;
+}
+
+// Initial state
+const initialState: UserState = {
+ users: [],
+ loading: false,
+ error: null,
+};
+
+// Async thunk to fetch user list
+export const userList = createAsyncThunk("users/fetchUsers", async () => {
+ try {
+ const response = await axios.get("/api/users"); // Adjust the API endpoint as needed
+ return response.data;
+ } catch (error: any) {
+ throw new Error(error.response?.data?.message || "Failed to fetch users");
+ }
+});
+
+const userSlice = createSlice({
+ name: "users",
+ initialState,
+ reducers: {},
+ extraReducers: (builder) => {
+ builder
+ .addCase(userList.pending, (state) => {
+ state.loading = true;
+ state.error = null;
+ })
+ .addCase(userList.fulfilled, (state, action: PayloadAction) => {
+ state.loading = false;
+ state.users = action.payload;
+ })
+ .addCase(userList.rejected, (state, action) => {
+ state.loading = false;
+ state.error = action.error.message || "Failed to fetch users";
+ });
+ },
+});
+
+export default userSlice.reducer;
diff --git a/src/router.tsx b/src/router.tsx
index 06b35b6..34590b2 100644
--- a/src/router.tsx
+++ b/src/router.tsx
@@ -1,8 +1,4 @@
-import {
- Routes as BaseRoutes,
- Navigate,
- Route,
-} from "react-router-dom";
+import { Routes as BaseRoutes, Navigate, Route } from "react-router-dom";
import React, { lazy, Suspense } from "react";
import LoadingComponent from "./components/Loading";
import DashboardLayout from "./layouts/DashboardLayout";
@@ -15,6 +11,7 @@ const Vehicles = lazy(() => import("./pages/Vehicles"));
const AdminList = lazy(() => import("./pages/AdminList"));
const ProfilePage = lazy(() => import("./pages/ProfilePage"));
const NotFoundPage = lazy(() => import("./pages/NotFound"));
+const UserList = lazy(() => import("./pages/UserList"));
interface ProtectedRouteProps {
caps: string[];
@@ -77,6 +74,15 @@ export default function AppRouter() {
/>
}
/>
+ }
+ />
+ }
+ />
{/* Catch-all Route */}
- } />
+ } />
);