diff --git a/src/components/layout/Navbar.jsx b/src/components/layout/Navbar.jsx
index 6d47ae8..6881e70 100644
--- a/src/components/layout/Navbar.jsx
+++ b/src/components/layout/Navbar.jsx
@@ -4,6 +4,7 @@ import { useAppDispatch, useAppSelector } from '../../store/hooks';
import { selectCurrentUser } from '../../features/auth/authSelectors';
import { logoutUser } from '../../features/auth/authThunks';
import { toastSuccess } from '../../utils/toast';
+import { useRole } from '../../hooks/useRole';
const NAV_LINKS = [
{ label: 'How it works', to: '/how-it-works' },
@@ -24,6 +25,7 @@ export default function Navbar() {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const user = useAppSelector(selectCurrentUser);
+ const { isAdmin } = useRole();
const [menuOpen, setMenuOpen] = useState(false);
const [avatarOpen, setAvatarOpen] = useState(false);
@@ -365,6 +367,12 @@ export default function Navbar() {
{user.name}
setAvatarOpen(false)}>Dashboard
+ {isAdmin && (
+ setAvatarOpen(false)}>Admin Panel
+ )}
+ {!isAdmin && (
+ setAvatarOpen(false)}>Create Campaign
+ )}
setAvatarOpen(false)}>Profile
setAvatarOpen(false)}>Settings
@@ -417,6 +425,12 @@ export default function Navbar() {
{user ? (
<>
Dashboard
+ {isAdmin && (
+ Admin Panel
+ )}
+ {!isAdmin && (
+ Create Campaign
+ )}
Profile
Settings
diff --git a/src/hooks/useRole.js b/src/hooks/useRole.js
new file mode 100644
index 0000000..c8e2ceb
--- /dev/null
+++ b/src/hooks/useRole.js
@@ -0,0 +1,21 @@
+import { useAppSelector } from '../store/hooks';
+import { selectCurrentUser } from '../features/auth/authSelectors';
+
+/**
+ * Custom hook to determine user roles
+ * @returns {Object} { isAdmin: boolean, isUser: boolean }
+ */
+export const useRole = () => {
+ const user = useAppSelector(selectCurrentUser);
+
+ // Determine if user is admin based on role property
+ const isAdmin = user?.role === 'admin';
+
+ // Determine if user is a regular user (authenticated but not admin)
+ const isUser = !!user && user?.role !== 'admin';
+
+ return {
+ isAdmin,
+ isUser,
+ };
+};
diff --git a/src/pages/CampaignDetails.jsx b/src/pages/CampaignDetails.jsx
index 6330275..e93c243 100644
--- a/src/pages/CampaignDetails.jsx
+++ b/src/pages/CampaignDetails.jsx
@@ -1,12 +1,76 @@
-import { useParams } from 'react-router-dom';
+import { useParams, useNavigate } from 'react-router-dom';
+import { useAppSelector } from '../store/hooks';
+import { selectCurrentUser } from '../features/auth/authSelectors';
+import { useState } from 'react';
const CampaignDetails = () => {
const { id } = useParams();
+ const navigate = useNavigate();
+ const user = useAppSelector(selectCurrentUser);
+
+ // TODO: Replace with actual API call to fetch campaign by id
+ // For now, using mock data structure
+ const [campaign] = useState({
+ id: id,
+ title: 'Sample Campaign',
+ description: 'This is a sample campaign description',
+ ownerId: null, // This should come from the API response
+ ownerName: 'Campaign Owner',
+ // ... other campaign fields
+ });
+
+ // Check if current user is the campaign owner
+ const isOwner = user && campaign?.ownerId === user.id;
+
+ const handleEdit = () => {
+ navigate(`/campaign/${id}/edit`);
+ };
+
+ const handleDelete = () => {
+ if (window.confirm('Are you sure you want to delete this campaign?')) {
+ // TODO: Implement delete campaign API call
+ console.log('Deleting campaign:', id);
+ // After successful deletion, redirect to explore page
+ // navigate('/explore');
+ }
+ };
return (
-
-
Campaign Details
-
Viewing details for campaign ID: {id}
+
+
+
+
+
+ {campaign.title}
+
+
Campaign ID: {id}
+
+
+ {/* Edit and Delete buttons - only visible to campaign owner */}
+ {isOwner && (
+
+
+
+
+ )}
+
+
+
+
{campaign.description}
+
+
+ {/* TODO: Add more campaign details here */}
+
);
};
diff --git a/src/routes/AdminRoute.jsx b/src/routes/AdminRoute.jsx
new file mode 100644
index 0000000..e94de9c
--- /dev/null
+++ b/src/routes/AdminRoute.jsx
@@ -0,0 +1,24 @@
+import { Navigate } from 'react-router-dom';
+import { useRole } from '../hooks/useRole';
+
+/**
+ * AdminRoute - A route wrapper that only allows admin users
+ * Redirects non-admin users to /dashboard
+ *
+ * @param {Object} props - Component props
+ * @param {React.ReactNode} props.children - The component to render if user is admin
+ * @returns {React.ReactElement} Either the children or a redirect
+ */
+const AdminRoute = ({ children }) => {
+ const { isAdmin } = useRole();
+
+ // If user is not an admin, redirect to dashboard
+ if (!isAdmin) {
+ return
;
+ }
+
+ // User is admin, render the protected component
+ return children;
+};
+
+export default AdminRoute;
diff --git a/src/routes/AppRouter.jsx b/src/routes/AppRouter.jsx
index 9775d6b..4402e15 100644
--- a/src/routes/AppRouter.jsx
+++ b/src/routes/AppRouter.jsx
@@ -6,6 +6,7 @@ import GlobalLoadingWrapper from '../components/common/GlobalLoadingWrapper';
import Spinner from '../components/common/Spinner';
import NotFound from '../pages/NotFound';
import ErrorTest from '../components/common/ErrorTest';
+import AdminRoute from './AdminRoute';
// Auth pages
import Login from '../pages/Login';
@@ -51,7 +52,11 @@ const AppRouter = () => {
{/* App pages */}
} />
-
} />
+
+
+
+ } />
{/* 404 */}
} />