diff --git a/src/components/AddEditCategoryModal/index.tsx b/src/components/AddEditCategoryModal/index.tsx index 9802f69..63d7686 100644 --- a/src/components/AddEditCategoryModal/index.tsx +++ b/src/components/AddEditCategoryModal/index.tsx @@ -102,7 +102,12 @@ const AddEditCategoryModal: React.FC = ({ return ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="add-edit-category-modal" > = ({ message: "Maximum 30 characters allowed", }, + pattern: { + value: /^[A-Za-z\s]+$/, // Only letters and spaces are allowed + message: + "Admin Name must only contain letters and spaces", + }, }} render={({ field }) => ( = ({ rules={{ required: "Email is required", pattern: { - value: /\S+@\S+\.\S+/, + value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, message: - "Please enter a valid email address.", + "Please enter a valid email address (e.g., example@domain.com).", }, }} render={({ field }) => ( diff --git a/src/components/AddManagerModal/index.tsx b/src/components/AddManagerModal/index.tsx index 8094776..d7c0588 100644 --- a/src/components/AddManagerModal/index.tsx +++ b/src/components/AddManagerModal/index.tsx @@ -1,22 +1,27 @@ - import { Controller, useForm } from "react-hook-form"; -import { Box, Button, Typography, Modal, IconButton, InputAdornment } from "@mui/material"; +import { + Box, + Button, + Typography, + Modal, + IconButton, + InputAdornment, +} from "@mui/material"; import CloseIcon from "@mui/icons-material/Close"; import { Visibility, VisibilityOff } from "@mui/icons-material"; import { useDispatch } from "react-redux"; -import { addManager } from "../../redux/slices/managerSlice"; +import { addManager, managerList } from "../../redux/slices/managerSlice"; import { CustomIconButton, CustomTextField, } from "../AddUserModel/styled.css.tsx"; -import React from "react"; +import React, { useState, useRef } from "react"; -type Props = { - open: boolean; - handleClose: () => void; -}; - -export default function AddManagerModal({ open, handleClose }: Props) { +export default function AddManagerModal({ + open, + handleClose, + handleAddManager, +}) { const dispatch = useDispatch(); const { control, @@ -25,22 +30,24 @@ export default function AddManagerModal({ open, handleClose }: Props) { formState: { errors }, reset, } = useForm(); - const [showPassword, setShowPassword] = React.useState(false); + const [showPassword, setShowPassword] = useState(false); + + // Handle form submission const onSubmit = async (data: any) => { const managerData = { name: data.name, email: data.email, phone: data.phone, registeredAddress: data.registeredAddress, - roleId: data.role, - password: data.password, - roleName: "Manager", // Add a role name (you can replace this with a dynamic value if needed) + password: data.password, + roleName: "Manager", // You can replace this with dynamic role if needed }; try { // Dispatch the addManager action - await dispatch(addManager(managerData)).unwrap(); + await dispatch(addManager(managerData)); + dispatch(managerList()); handleClose(); // Close modal after successful addition reset(); // Reset form fields } catch (error) { @@ -48,15 +55,21 @@ export default function AddManagerModal({ open, handleClose }: Props) { } }; - // Toggle password visibility - const togglePasswordVisibility = () => { + + const togglePasswordVisibility = (e: React.MouseEvent) => { + e.preventDefault(); // Prevent focus loss setShowPassword((prev) => !prev); - }; + }; return ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="add-manager-modal" > - {/* First Row - Manager Name */} - - {/* Manager Name */} - - - Manager Name - - - + {/* Manager Name */} + + + Manager Name + + - {/* Second Row - Email, Password */} - + {/* Email and Password */} + {/* Email */} - + Email @@ -158,91 +164,73 @@ export default function AddManagerModal({ open, handleClose }: Props) { {/* Password */} - - + + Password + + - - Password - - ( - - - {showPassword ? ( - - ) : ( - - )} - - - ), - }} - error={!!errors.password} - helperText={ - errors.password?.message - } - /> - )} - /> - - + render={({ field }) => ( + + + {showPassword ? ( + + ) : ( + + )} + + + ), + }} + error={!!errors.password} + helperText={errors.password?.message} + /> + )} + /> + - {/* Third Row - Phone Number, Registered Address */} - - {/* Phone Number */} - + {/* Phone and Registered Address */} + + {/* Phone */} + Phone Number @@ -266,13 +254,7 @@ export default function AddManagerModal({ open, handleClose }: Props) { {/* Registered Address */} - + Registered Address diff --git a/src/components/AddUserModel/index.tsx b/src/components/AddUserModel/index.tsx index c07240c..69ec91b 100644 --- a/src/components/AddUserModel/index.tsx +++ b/src/components/AddUserModel/index.tsx @@ -93,7 +93,12 @@ const AddUserModal: React.FC = ({ return ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="add-user-modal" > = ({ message: "Maximum 30 characters allowed", }, + pattern: { + value: /^[A-Za-z\s]+$/, // Only letters and spaces are allowed + message: + "User Name must only contain letters and spaces", + }, }} render={({ field }) => ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="add-vehicle-modal" > @@ -232,7 +247,6 @@ export default function AddVehicleModal({ }} > -// -// -// -// ); -// }; -// export default EditManagerModal; import React, { useEffect, useState } from "react"; import { Box, @@ -323,7 +9,7 @@ import { import CloseIcon from "@mui/icons-material/Close"; import { useForm, Controller } from "react-hook-form"; import { useDispatch } from "react-redux"; -import { updateManager } from "../../redux/slices/managerSlice"; // Import the updateManager action +import { managerList, updateManager } from "../../redux/slices/managerSlice"; // Import the updateManager action import { CustomIconButton, CustomTextField, @@ -379,9 +65,6 @@ const EditManagerModal: React.FC = ({ const onSubmit = async (data: FormData) => { if (editRow) { - setLoading(true); // Start loading state - - // Dispatch the updateManager action from Redux try { await dispatch( updateManager({ @@ -394,7 +77,7 @@ const EditManagerModal: React.FC = ({ }, }) ).unwrap(); // Ensure that it throws an error if the update fails - + dispatch(managerList()); handleClose(); // Close modal on success reset(); // Reset form fields after submit } catch (error) { @@ -409,7 +92,12 @@ const EditManagerModal: React.FC = ({ return ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="edit-manager-modal" > = ({ {/* Horizontal Line */} - {/* Input Fields */} - - {/* Manager Name */} - + {/* Input Fields (2 inputs per row) */} + + {/* Manager Name and Email in one row */} + Manager Name ( + rules={{ + required: "Manager Name is required", + minLength: { + value: 3, + message: + "Minimum 3 characters required", + }, + maxLength: { + value: 30, + message: + "Maximum 30 characters allowed", + }, + pattern: { + value: /^[A-Za-z\s]+$/, // Only letters and spaces are allowed + message: + "Manager Name must only contain letters and spaces", + }, + }} + render={({ field }) => ( = ({ size="small" error={!!errors.name} helperText={errors.name?.message} + /> )} /> - {/* Registered Address */} - + + + Email + + ( + + )} + /> + + + {/* Registered Address and Phone Number in one row */} + Registered Address @@ -508,42 +223,7 @@ const EditManagerModal: React.FC = ({ /> - {/* Email */} - - - Email - - ( - - )} - /> - - - {/* Phone Number */} - + Phone Number diff --git a/src/components/EditVehicleModal/index.tsx b/src/components/EditVehicleModal/index.tsx index 3d51f09..fe9ef13 100644 --- a/src/components/EditVehicleModal/index.tsx +++ b/src/components/EditVehicleModal/index.tsx @@ -87,7 +87,12 @@ const EditVehicleModal: React.FC = ({ return ( { + if (reason === "backdropClick") { + return; + } + handleClose(); // Close modal when clicking cross or cancel + }} aria-labelledby="edit-vehicle-modal" > = ({ ( = ({ size="small" error={!!errors.name} helperText={errors.name?.message} + /> )} /> diff --git a/src/components/MenuContent/index.tsx b/src/components/MenuContent/index.tsx index 25539bb..acb72fa 100644 --- a/src/components/MenuContent/index.tsx +++ b/src/components/MenuContent/index.tsx @@ -52,7 +52,7 @@ export default function MenuContent({ hidden }: PropType) { userRole === "admin" && { text: "Vehicles", icon: , - url: "/panel/vehicles", // Placeholder for now + url: "/panel/vehicle-list", // Placeholder for now }, ]; diff --git a/src/components/Modals/LogOutModal/index.tsx b/src/components/Modals/LogOutModal/index.tsx index 4f788d6..088d075 100644 --- a/src/components/Modals/LogOutModal/index.tsx +++ b/src/components/Modals/LogOutModal/index.tsx @@ -1,81 +1,112 @@ import { Box, Button, Modal, Typography } from "@mui/material"; -import CloseIcon from '@mui/icons-material/Close'; - +import CloseIcon from "@mui/icons-material/Close"; + type Props = { - open: boolean; - setLogoutModal: Function; - handlelogout: any; + open: boolean; + setLogoutModal: Function; + handlelogout: any; }; - + const style = { - position: "absolute", - top: "50%", - left: "50%", - transform: "translate(-50%, -50%)", - width: 330, - bgcolor: "background.paper", - borderRadius: 1.5, - boxShadow: 24, - p: 3, + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 330, + bgcolor: "background.paper", + borderRadius: 1.5, + boxShadow: 24, + p: 3, }; - + const btnStyle = { py: 1, px: 5, width: "50%", textTransform: "capitalize" }; - + export default function LogoutModal({ - open, - setLogoutModal, - handlelogout, + open, + setLogoutModal, + handlelogout, }: Props) { - return ( - - - - - Logout - setLogoutModal(false)} sx={{ cursor: "pointer", display: "flex", alignItems: "center" }}> - - - - - - Are you sure you want to Logout? - - - - - - - - ); -} \ No newline at end of file + // Function to prevent closing the modal when clicking outside + const handleClose = (event: React.SyntheticEvent) => { + // Close only when clicking the close button, not the backdrop + setLogoutModal(false); + }; + + return ( + + reason !== "backdropClick" && setLogoutModal(false) + } // Prevent closing on backdrop click + aria-labelledby="modal-modal-title" + aria-describedby="modal-modal-description" + BackdropProps={{ + onClick: (e) => e.stopPropagation(), // Stop propagation on backdrop click to prevent closing the modal + }} + > + + + + Logout + setLogoutModal(false)} + sx={{ + cursor: "pointer", + display: "flex", + alignItems: "center", + }} + > + + + + + + Are you sure you want to Logout? + + + + + + + + ); +} diff --git a/src/components/Modals/UserViewModal/index.tsx b/src/components/Modals/UserViewModal/index.tsx new file mode 100644 index 0000000..ffb6c27 --- /dev/null +++ b/src/components/Modals/UserViewModal/index.tsx @@ -0,0 +1,117 @@ +import React, { useEffect, useState } from "react"; +import { Box, Modal, Typography, Divider, Grid } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; +import { useSelector } from "react-redux"; +import { RootState } from "../../../redux/reducers"; + +type Props = { + open: boolean; + setViewModal: Function; + handleView: (id: string | undefined) => void; + id?: string | undefined; +}; + +const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: 400, + bgcolor: "background.paper", + borderRadius: 2, + boxShadow: "0px 4px 20px rgba(0, 0, 0, 0.15)", + p: 4, + display: "flex", + flexDirection: "column", + alignItems: "center", + gap: 2, +}; + +export default function UserViewModal({ open, setViewModal, id }: Props) { + const { users } = useSelector( + (state: RootState) => state.userReducer // Assuming users are stored in userReducer + ); + const [selectedUser, setSelectedUser] = useState(null); + + useEffect(() => { + if (id) { + const user = users.find((user) => user.id === id); + setSelectedUser(user || null); + } + }, [id, users]); + + return ( + + + + + + {selectedUser?.name || "User"}'s Details + + setViewModal(false)} + sx={{ + cursor: "pointer", + display: "flex", + alignItems: "center", + }} + > + + + + + + + + {selectedUser ? ( + + + + Name:{" "} + + {selectedUser.name} + + + + + + Email:{" "} + + {selectedUser.email} + + + + + + Phone:{" "} + + {selectedUser.phone ?? "N/A"} + + + + + ) : ( + + No user found with this ID + + )} + + + ); +} diff --git a/src/pages/Auth/Login/index.tsx b/src/pages/Auth/Login/index.tsx index 45cadd2..974bafa 100644 --- a/src/pages/Auth/Login/index.tsx +++ b/src/pages/Auth/Login/index.tsx @@ -9,9 +9,9 @@ import { TextField, Typography, Grid, - IconButton, + Link, - InputAdornment + InputAdornment, } from "@mui/material"; import { useForm, Controller, SubmitHandler } from "react-hook-form"; import { useDispatch } from "react-redux"; @@ -22,7 +22,9 @@ import { toast } from "sonner"; import { useNavigate } from "react-router-dom"; import { Visibility, VisibilityOff } from "@mui/icons-material"; import { Card, SignInContainer } from "./styled.css.tsx"; - +import { + CustomIconButton, +} from "../../../components/AddUserModel/styled.css.tsx"; interface ILoginForm { email: string; password: string; @@ -30,9 +32,8 @@ interface ILoginForm { export default function Login(props: { disableCustomTheme?: boolean }) { const [open, setOpen] = React.useState(false); - const [isClicked, setIsClicked] = React.useState(false); const [showPassword, setShowPassword] = React.useState(false); - + const { control, handleSubmit, @@ -48,17 +49,22 @@ export default function Login(props: { disableCustomTheme?: boolean }) { const handleClose = () => { setOpen(false); }; - + + const togglePasswordVisibility = (e: React.MouseEvent) => { + e.preventDefault(); // Prevent focus loss + setShowPassword((prev) => !prev); + }; + const onSubmit: SubmitHandler = async (data: ILoginForm) => { - try { - const response = await dispatch(loginUser(data)).unwrap(); - if (response?.data?.token) { - router("/panel/dashboard"); + try { + const response = await dispatch(loginUser(data)).unwrap(); + if (response?.data?.token) { + router("/panel/dashboard"); + } + } catch (error: any) { + console.log("Login failed:", error); } - } catch (error: any) { - console.log("Login failed:", error); - } -}; + }; return ( @@ -80,21 +86,19 @@ export default function Login(props: { disableCustomTheme?: boolean }) { {/* Form Section */} - + item + xs={12} + md={5} + sx={{ + backgroundColor: "black", + display: "flex", + justifyContent: "center", + alignItems: "center", + flexDirection: "column", + padding: { xs: "2rem", md: "3rem", lg: "3rem" }, + height: "auto", + }} + > - - + - Login - - Log in with your email and password - + + Login + + + Log in with your email and password + + {/* -------------------------------- Email Field ----------------- */} + + + Email + + ( + + )} + /> + -{/* -------------------------------- Email Field ----------------- */} - - - Email - - ( - - )} - /> - - - -{/* -------------------------------- Password Field ----------------- */} - - - Password - - ( - setShowPassword((prev) => !prev)} - edge="end" - sx={{ - color: "white", - padding: 0, - margin: 0, - backgroundColor: "transparent", - border: "none", - boxShadow: "none", - "&:hover": { backgroundColor: "transparent" }, - "&:focus": { outline: "none", border: "none" }, - }} - > - {showPassword ? : } - - ), - }} - sx={{ - "& .MuiOutlinedInput-root": { - backgroundColor: "#1E1F1F", - borderRadius: "4px", - "& fieldset": { borderColor: "#4b5255" }, - "&:hover fieldset": { borderColor: "#4b5255" }, - "&.Mui-focused fieldset": { borderColor: "#4b5255" }, - }, - "& input": { - color: "white", - fontSize: { xs: "0.9rem", sm: "1rem" }, - fontFamily: "Gilroy, sans-serif", - }, - "& .MuiInputBase-input::placeholder": { - color: "white", - opacity: 1, - fontFamily: "Gilroy, sans-serif", - }, - }} - /> - )} - /> - - + {/* -------------------------------- Password Field ----------------- */} + + + Password + + ( + + + {showPassword ? ( + + ) : ( + + )} + + + ), + }} + sx={{ + "& .MuiOutlinedInput-root": + { + backgroundColor: + "#1E1F1F", + borderRadius: "4px", + "& fieldset": { + borderColor: + "#4b5255", + }, + "&:hover fieldset": + { + borderColor: + "#4b5255", + }, + "&.Mui-focused fieldset": + { + borderColor: + "#4b5255", + }, + }, + "& input": { + color: "white", + fontSize: { + xs: "0.9rem", + sm: "1rem", + }, + fontFamily: + "Gilroy, sans-serif", + }, + "& .MuiInputBase-input::placeholder": + { + color: "white", + opacity: 1, + fontFamily: + "Gilroy, sans-serif", + }, + }} + /> + )} + /> + - - - } - label="Remember me" -/> - - - Forgot password? - + + } + label="Remember me" + /> + + Forgot password? + (false); @@ -43,7 +34,7 @@ export default function ManagerList() { }, [dispatch]); const handleClickOpen = () => { - setRowData(null); // Reset row data when opening for new admin + setRowData(null); // Reset row data when opening for new manager setAddModalOpen(true); }; @@ -77,56 +68,64 @@ export default function ManagerList() { registeredAddress: string ) => { try { - // Creating the managerData object to match the expected payload structure - const managerData = { - name, - email, - phone, - registeredAddress, - }; - - // Dispatching the updateManager action with the correct payload structure - await dispatch(updateManager({ id, managerData })); - await dispatch(managerList()); // Refresh the manager list after updating - handleCloseModal(); // Close the modal after updating + await dispatch( + updateManager({ + id, + name, + email, + phone, + registeredAddress, + }) + ); + await dispatch(managerList()); // Refresh the list after update + handleCloseModal(); // Close modal after update } catch (error) { console.error("Update failed", error); } }; - // Remove 'stationName' from columns const categoryColumns: Column[] = [ { id: "srno", label: "Sr No" }, { id: "name", label: "Name" }, { id: "email", label: "Email" }, { id: "phone", label: "Phone" }, { id: "registeredAddress", label: "Station Location" }, - { id: "action", label: "Action", align: "center" }, ]; - // Update rows to remove 'stationName' - const categoryRows = managers?.map( - ( - manager: { - id: number; - name: string; - email: string; - phone: string; - registeredAddress: string; - }, - index: number - ) => ({ - id: manager?.id, - srno: index + 1, - name: manager?.name, - email: manager?.email, - phone: manager.phone ?? "NA", - registeredAddress: manager?.registeredAddress ?? "NA", - }) + const filteredManagers = managers?.filter( + (manager) => + manager.name?.toLowerCase().includes(searchTerm.toLowerCase()) || + manager.email?.toLowerCase().includes(searchTerm.toLowerCase()) || + manager.phone?.toLowerCase().includes(searchTerm.toLowerCase()) || + manager.registeredAddress + ?.toLowerCase() + .includes(searchTerm.toLowerCase()) ); + const categoryRows = filteredManagers?.length + ? filteredManagers?.map( + ( + manager: { + id: number; + name: string; + email: string; + phone: string; + registeredAddress: string; + }, + index: number + ) => ({ + id: manager?.id, + srno: index + 1, + name: manager?.name, + email: manager?.email, + phone: manager.phone ?? "NA", + registeredAddress: manager?.registeredAddress ?? "NA", + }) + ) + : []; + return ( <> ("fetchManagers", async (_, { rejectWithValue }) => { try { + const token = localStorage?.getItem("authToken"); + if (!token) throw new Error("No token found"); + const response = await http.get("manager-list"); if (!response.data?.data) throw new Error("Invalid API response"); return response.data.data; @@ -46,7 +49,6 @@ export const managerList = createAsyncThunk< // Create Manager (Async Thunk) export const addManager = createAsyncThunk< - Manager, Manager, { rejectValue: string } >("addManager", async (data, { rejectWithValue }) => { @@ -103,7 +105,7 @@ export const deleteManager = createAsyncThunk< // Create Slice const managerSlice = createSlice({ - name: "maanger", + name: "manager", initialState, reducers: {}, extraReducers: (builder) => { @@ -147,13 +149,13 @@ const managerSlice = createSlice({ }) .addCase(updateManager.fulfilled, (state, action) => { state.loading = false; - // const updatedManager = action.payload; - // const index = state.managers.findIndex( - // (manager) => manager.id === updatedManager.id - // ); - // if (index !== -1) { - // state.managers[index] = updatedManager; // Update the manager in the state - // } + const updatedManager = action.payload; + const index = state.managers.findIndex( + (manager) => manager.id === updatedManager.id + ); + if (index !== -1) { + state.managers[index] = updatedManager; // Update the manager in the state + } }) .addCase(updateManager.rejected, (state, action) => { state.loading = false; @@ -166,9 +168,6 @@ const managerSlice = createSlice({ }) .addCase(deleteManager.fulfilled, (state, action) => { state.loading = false; - state.managers = state.managers.filter( - (manager) => manager.id !== action.payload - ); }) .addCase(deleteManager.rejected, (state, action) => { state.loading = false; diff --git a/src/redux/slices/userSlice.ts b/src/redux/slices/userSlice.ts index 2347971..20ab9b4 100644 --- a/src/redux/slices/userSlice.ts +++ b/src/redux/slices/userSlice.ts @@ -56,7 +56,6 @@ export const createUser = createAsyncThunk< name: string; email: string; phone: string; - }, { rejectValue: string } >("/CreateUser", async (data, { rejectWithValue }) => { @@ -70,8 +69,6 @@ export const createUser = createAsyncThunk< } }); - - export const updateUser = createAsyncThunk( "updateUser", async ({ id, ...userData }: User, { rejectWithValue }) => { @@ -87,6 +84,24 @@ export const updateUser = createAsyncThunk( } } ); + +export const deleteUser = createAsyncThunk< + string, + string, + { rejectValue: string } +>("deleteUser", async (id, { rejectWithValue }) => { + try { + const response = await http.delete(`/${id}/delete-user`); + toast.success(response.data?.message); + return id; + } catch (error: any) { + toast.error("Error deleting the user" + error); + + return rejectWithValue( + error.response?.data?.message || "An error occurred" + ); + } +}); const userSlice = createSlice({ name: "fetchUsers", initialState, @@ -133,6 +148,18 @@ const userSlice = createSlice({ }) .addCase(updateUser.rejected, (state) => { state.loading = false; + }) + .addCase(deleteUser.pending, (state) => { + state.loading = true; + }) + .addCase(deleteUser.fulfilled, (state, action) => { + state.loading = false; + state.users = state.users.filter( + (user) => String(user.id) !== String(action.payload) + ); + }) + .addCase(deleteUser.rejected, (state) => { + state.loading = false; }); }, }); diff --git a/src/router.tsx b/src/router.tsx index b1b40a5..fd15284 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -2,30 +2,31 @@ 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"; -import RoleList from "./pages/RoleList"; -import AddEditRolePage from "./pages/AddEditRolePage"; -import VehicleList from "./pages/VehicleList"; +// import RoleList from "./pages/RoleList"; +// import AddEditRolePage from "./pages/AddEditRolePage"; +// import VehicleList from "./pages/VehicleList"; // Page imports const Login = lazy(() => import("./pages/Auth/Login")); const SignUp = lazy(() => import("./pages/Auth/SignUp")); const Dashboard = lazy(() => import("./pages/Dashboard")); -const Vehicles = lazy(() => import("./pages/VehicleList")); +const VehicleList = lazy(() => import("./pages/VehicleList")); const AdminList = lazy(() => import("./pages/AdminList")); const ProfilePage = lazy(() => import("./pages/ProfilePage")); const NotFoundPage = lazy(() => import("./pages/NotFound")); const UserList = lazy(() => import("./pages/UserList")); -const PermissionsTable = lazy(() => import("./pages/PermissionTable")); +const AddEditRolePage = lazy(() => import("./pages/AddEditRolePage")); +const RoleList = lazy(() => import("./pages/RoleList")); const ManagerList = lazy(() => import("./pages/ManagerList")); interface ProtectedRouteProps { - caps: string[]; + // caps: string[]; component: React.ReactNode; } // Protected Route Component -const ProtectedRoute: React.FC = ({ caps, component }) => { +const ProtectedRoute: React.FC = ({ component }) => { if (!localStorage.getItem("authToken")) { return ; } @@ -42,11 +43,6 @@ export default function AppRouter() { {/* Auth Routes */} - } - index - /> } /> } /> @@ -57,25 +53,17 @@ export default function AppRouter() { path="dashboard" element={ } /> } /> - } - /> - } - /> + } /> } @@ -84,7 +72,7 @@ export default function AppRouter() { path="user-list" element={ } /> } @@ -94,7 +82,7 @@ export default function AppRouter() { path="manager-list" element={ } /> } @@ -105,7 +93,7 @@ export default function AppRouter() { path="role-list" element={ } /> } @@ -114,7 +102,7 @@ export default function AppRouter() { path="vehicle-list" element={ } /> } @@ -123,7 +111,7 @@ export default function AppRouter() { path="permissions" element={ } /> } @@ -132,7 +120,7 @@ export default function AppRouter() { path="profile" element={ } /> }