diff --git a/src/app/store.ts b/src/app/store.ts index e52abd69..28d1483a 100644 --- a/src/app/store.ts +++ b/src/app/store.ts @@ -17,6 +17,7 @@ import buyerSlice from '@/app/Dashboard/buyerSlice'; import orderSlice from './Dashboard/orderSlice'; import ordersSliceReducer from '@/features/Orders/ordersSlice'; +import userRoleSlice from '@/features/userRole/userRoleSlice'; export const store = configureStore({ reducer: { @@ -35,6 +36,7 @@ export const store = configureStore({ orders: ordersSliceReducer, product: addProductSlice, DeshboardProducts: dashboardProductsSlice, + userRoles: userRoleSlice, }, }); diff --git a/src/components/dashBoard/DashboardSideNav.tsx b/src/components/dashBoard/DashboardSideNav.tsx index e64efc39..946f52a6 100644 --- a/src/components/dashBoard/DashboardSideNav.tsx +++ b/src/components/dashBoard/DashboardSideNav.tsx @@ -7,6 +7,7 @@ import { Box, ChevronDown, ChevronRight, + User, } from 'lucide-react'; const sideBarItems = [ @@ -47,6 +48,20 @@ const sideBarItems = [ }, ], }, + { + name: 'User Role', + icon: , + subItems: [ + { + path: '/dashboard/userRole', + name: 'All Roles', + }, + { + path: '/products/addRole', + name: 'Add Role', + }, + ], + }, ]; interface SideBarItemProps { diff --git a/src/components/dashBoard/TableUserRole.tsx b/src/components/dashBoard/TableUserRole.tsx new file mode 100644 index 00000000..762a3fa0 --- /dev/null +++ b/src/components/dashBoard/TableUserRole.tsx @@ -0,0 +1,141 @@ +/* eslint-disable jsx-a11y/control-has-associated-label */ +import { useEffect, useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { FaRegTrashAlt } from 'react-icons/fa'; +import { MdOutlineEdit } from 'react-icons/md'; +import { RootState, AppDispatch } from '@/app/store'; +import { + fetchUserRoles, + deleteUserRole, +} from '@/features/userRole/userRoleSlice'; +import ConfirmationCard from './ConfirmationCard'; +import CircularPagination from './NavigateonPage'; + +function TableUserRole() { + const dispatch: AppDispatch = useDispatch(); + const { roles, status } = useSelector((state: RootState) => state.userRoles); + + const [isConfirmationModalVisible, setModalVisible] = useState(false); + const [itemSelected, setItemSelected] = useState(null); + const [mode, setMode] = useState(''); + + useEffect(() => { + dispatch(fetchUserRoles()); + }, [dispatch]); + + const handleDelete = (id: number) => { + setItemSelected(id); + setMode('delete'); + setModalVisible(true); + }; + + const confirmDelete = async () => { + if (itemSelected !== null) { + await dispatch(deleteUserRole(itemSelected)); + setModalVisible(false); + } + }; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const handleUpdate = (_id: number) => { + // Implement update functionality + }; + + const confirmUpdate = () => { + if (itemSelected !== null) { + // Implement update logic + } + setModalVisible(false); + }; + + return ( +
+
+
User Roles
+
+
+ + + + + + + + + + + {status === 'loading' && + Array(6) + .fill(null) + .map((_, index) => ( + + + + ))} + {status === 'failed' && + Array(6) + .fill(null) + .map((_, index) => ( + + + + ))} + {status === 'succeeded' && + roles && + roles.map((role) => ( + + + + + + ))} + +
+ ID + + Role Name + + Action +
+
+
+
+ Failed to load roles... +
+
{role.id}{role.name} + handleUpdate(role.id)} + /> + handleDelete(role.id)} + /> +
+ {isConfirmationModalVisible && ( + setModalVisible(false)} + mode={mode} + /> + )} + {}} + /> +
+
+ ); +} + +export default TableUserRole; diff --git a/src/features/userRole/userRoleSlice.tsx b/src/features/userRole/userRoleSlice.tsx new file mode 100644 index 00000000..e6a05ae1 --- /dev/null +++ b/src/features/userRole/userRoleSlice.tsx @@ -0,0 +1,71 @@ +import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit'; +import axios from 'axios'; + +interface UserRole { + id: number; + name: string; +} + +interface UserRoleState { + roles: UserRole[]; + status: 'idle' | 'loading' | 'succeeded' | 'failed'; + error: string | null; +} + +const initialState: UserRoleState = { + roles: [], + status: 'idle', + error: null, +}; + +export const fetchUserRoles = createAsyncThunk( + 'userRoles/fetchUserRoles', + async () => { + const response = await axios.get( + `${import.meta.env.VITE_BASE_URL}/roles/get_roles` + ); + console.log(response.data.roles); + return response.data.roles; + } +); + +export const deleteUserRole = createAsyncThunk( + 'userRoles/deleteUserRole', + async (id: number) => { + await axios.delete(`/api/roles/${id}`); + return id; + } +); + +const userRoleSlice = createSlice({ + name: 'userRoles', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder + .addCase(fetchUserRoles.pending, (state) => { + state.status = 'loading'; + }) + .addCase( + fetchUserRoles.fulfilled, + (state, action: PayloadAction) => { + state.status = 'succeeded'; + state.roles = action.payload; + } + ) + .addCase(fetchUserRoles.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message || 'Failed to fetch roles'; + }) + .addCase( + deleteUserRole.fulfilled, + (state, action: PayloadAction) => { + state.roles = state.roles.filter( + (role) => role.id !== action.payload + ); + } + ); + }, +}); + +export default userRoleSlice.reducer; diff --git a/src/routes/AppRoutes.tsx b/src/routes/AppRoutes.tsx index 5b59ba04..a12c8c21 100644 --- a/src/routes/AppRoutes.tsx +++ b/src/routes/AppRoutes.tsx @@ -18,6 +18,7 @@ import { Orders } from '@/components/Orders/Orders'; import AddProducts from '@/components/dashBoard/addProducts'; import ProductDetails from '@/pages/ProductDetails'; import ProtectedRoute from '@/components/ProtectedRoute'; +import TableUserRole from '@/components/dashBoard/TableUserRole'; function AppRoutes() { return ( @@ -62,6 +63,7 @@ function AppRoutes() { element={} /> } /> + } /> } /> } />