diff --git a/src/App.jsx b/src/App.jsx
index 24ee150..efdf99b 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -18,6 +18,7 @@ import AltTextRatingTool from './components/AltTextRating/AltTextRatingTool';
import UserProfile from './components/UserProfile/UserProfile';
import ZenPage from './components/ZenPage';
import CompareScores from './components/CompareScores/CompareScores';
+import AdminRoute from './components/Admin/AdminRoute';
import "./App.css";
const App = () => {
@@ -27,29 +28,34 @@ const App = () => {
-
- {/* All routes are now public */}
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- {/* Handle both DIDs and regular usernames */}
- } />
- {/* Default routes */}
- } />
- } />
-
+
+ {/* All routes are now public */}
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+ {/* Admin Route */}
+ } />
+
+ {/* Handle both DIDs and regular usernames */}
+ } />
+
+ {/* Default routes */}
+ } />
+ } />
+
diff --git a/src/components/Admin/AdminPanel.css b/src/components/Admin/AdminPanel.css
new file mode 100644
index 0000000..5e8fc6d
--- /dev/null
+++ b/src/components/Admin/AdminPanel.css
@@ -0,0 +1,405 @@
+/* src/components/Admin/AdminPanel.css */
+.admin-panel {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 20px;
+ color: #333;
+ }
+
+ /* Header */
+ .admin-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 20px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid #eee;
+ }
+
+ .admin-header h1 {
+ margin: 0;
+ color: #333;
+ font-size: 24px;
+ }
+
+ /* Container layout */
+ .admin-container {
+ display: grid;
+ grid-template-columns: 300px 1fr;
+ gap: 20px;
+ height: calc(100vh - 120px);
+ }
+
+ /* Resources sidebar */
+ .resources-sidebar {
+ background-color: #f8f9fa;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ }
+
+ .sidebar-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px;
+ background-color: #f0f2f5;
+ border-bottom: 1px solid #ddd;
+ }
+
+ .sidebar-header h2 {
+ margin: 0;
+ font-size: 18px;
+ }
+
+ .resources-list {
+ overflow-y: auto;
+ flex-grow: 1;
+ }
+
+ .resource-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 12px 15px;
+ border-bottom: 1px solid #eee;
+ cursor: pointer;
+ transition: background-color 0.2s;
+ }
+
+ .resource-item:hover {
+ background-color: #f0f2f5;
+ }
+
+ .resource-item.selected {
+ background-color: #e6f7ff;
+ border-left: 3px solid #1890ff;
+ }
+
+ .resource-item-name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ flex-grow: 1;
+ }
+
+ .resource-item-actions {
+ display: flex;
+ gap: 5px;
+ visibility: hidden;
+ }
+
+ .resource-item:hover .resource-item-actions {
+ visibility: visible;
+ }
+
+ /* Resource editor */
+ .resource-editor {
+ background-color: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+ padding: 20px;
+ overflow-y: auto;
+ height: 100%;
+ }
+
+ .resource-editor h2 {
+ margin-top: 0;
+ margin-bottom: 20px;
+ color: #333;
+ }
+
+ /* Form styling */
+ .form-row {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 15px;
+ margin-bottom: 15px;
+ }
+
+ .form-group {
+ margin-bottom: 15px;
+ }
+
+ .form-group label {
+ display: block;
+ margin-bottom: 5px;
+ font-weight: 500;
+ color: #555;
+ }
+
+ .form-group input[type="text"],
+ .form-group input[type="url"],
+ .form-group input[type="number"],
+ .form-group textarea {
+ width: 100%;
+ padding: 10px;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 14px;
+ }
+
+ .form-group textarea {
+ resize: vertical;
+ min-height: 100px;
+ }
+
+ .checkbox-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .checkbox-group input[type="checkbox"] {
+ margin: 0;
+ }
+
+ .checkbox-group label {
+ margin-bottom: 0;
+ }
+
+ /* Categories and Tags sections */
+ .categories-section,
+ .tags-section {
+ background-color: #f8f9fa;
+ border-radius: 6px;
+ padding: 15px;
+ border: 1px solid #eee;
+ }
+
+ .section-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+ }
+
+ .section-header label {
+ font-weight: 600;
+ margin-bottom: 0;
+ }
+
+ .checkbox-list {
+ max-height: 200px;
+ overflow-y: auto;
+ }
+
+ .checkbox-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 8px;
+ gap: 8px;
+ }
+
+ .checkbox-item label {
+ margin-bottom: 0;
+ font-weight: normal;
+ }
+
+ /* Form actions */
+ .form-actions {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-top: 20px;
+ }
+
+ /* Buttons */
+ button {
+ cursor: pointer;
+ border: none;
+ border-radius: 4px;
+ font-size: 14px;
+ transition: background-color 0.2s, opacity 0.2s;
+ }
+
+ .add-new-button {
+ background-color: #1890ff;
+ color: white;
+ padding: 6px 12px;
+ font-size: 13px;
+ }
+
+ .add-new-button:hover {
+ background-color: #40a9ff;
+ }
+
+ .delete-button {
+ background: none;
+ padding: 3px 6px;
+ font-size: 16px;
+ opacity: 0.7;
+ }
+
+ .delete-button:hover {
+ opacity: 1;
+ background-color: #ffebee;
+ }
+
+ .add-item-button {
+ background-color: #f5f5f5;
+ color: #333;
+ padding: 4px 8px;
+ font-size: 12px;
+ border: 1px solid #ddd;
+ }
+
+ .add-item-button:hover {
+ background-color: #e0e0e0;
+ }
+
+ .save-button {
+ background-color: #52c41a;
+ color: white;
+ padding: 10px 20px;
+ }
+
+ .save-button:hover {
+ background-color: #73d13d;
+ }
+
+ .cancel-button {
+ background-color: #f5f5f5;
+ color: #333;
+ padding: 10px 20px;
+ border: 1px solid #d9d9d9;
+ }
+
+ .cancel-button:hover {
+ background-color: #e6e6e6;
+ }
+
+ .logout-button {
+ background-color: #f5f5f5;
+ color: #333;
+ padding: 8px 16px;
+ border: 1px solid #d9d9d9;
+ }
+
+ .logout-button:hover {
+ background-color: #e6e6e6;
+ }
+
+ /* Alert messages */
+ .alert {
+ padding: 12px 15px;
+ margin-bottom: 20px;
+ border-radius: 4px;
+ font-weight: 500;
+ }
+
+ .alert.success {
+ background-color: #f6ffed;
+ border: 1px solid #b7eb8f;
+ color: #52c41a;
+ }
+
+ .alert.error {
+ background-color: #fff2f0;
+ border: 1px solid #ffccc7;
+ color: #f5222d;
+ }
+
+ /* Loading spinner */
+ .admin-loading {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ }
+
+ .loading-spinner {
+ border: 4px solid #f3f3f3;
+ border-top: 4px solid #1890ff;
+ border-radius: 50%;
+ width: 40px;
+ height: 40px;
+ animation: spin 1s linear infinite;
+ margin-bottom: 15px;
+ }
+
+ @keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+ }
+
+ /* Login form */
+ .admin-login-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ background-color: #f0f2f5;
+ }
+
+ .admin-login-card {
+ background-color: white;
+ border-radius: 8px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+ padding: 30px;
+ width: 100%;
+ max-width: 400px;
+ }
+
+ .admin-login-card h2 {
+ margin-top: 0;
+ margin-bottom: 20px;
+ text-align: center;
+ color: #333;
+ }
+
+ .login-button {
+ background-color: #1890ff;
+ color: white;
+ padding: 10px 0;
+ width: 100%;
+ font-size: 16px;
+ margin-top: 10px;
+ }
+
+ .login-button:hover {
+ background-color: #40a9ff;
+ }
+
+ .auth-error {
+ background-color: #fff2f0;
+ border: 1px solid #ffccc7;
+ color: #f5222d;
+ padding: 10px;
+ border-radius: 4px;
+ margin-bottom: 15px;
+ font-size: 14px;
+ }
+
+ /* Accessibility */
+ .sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border-width: 0;
+ }
+
+ /* Responsive design */
+ @media (max-width: 768px) {
+ .admin-container {
+ grid-template-columns: 1fr;
+ }
+
+ .form-row {
+ grid-template-columns: 1fr;
+ }
+
+ .resources-sidebar {
+ height: 300px;
+ }
+ }
\ No newline at end of file
diff --git a/src/components/Admin/AdminPanel.js b/src/components/Admin/AdminPanel.js
new file mode 100644
index 0000000..c13afa3
--- /dev/null
+++ b/src/components/Admin/AdminPanel.js
@@ -0,0 +1,685 @@
+// src/components/Admin/AdminPanel.jsx
+import React, { useState, useEffect } from 'react';
+import { supabase } from '../../lib/supabase';
+import './AdminPanel.css';
+
+const AdminPanel = () => {
+ // State management
+ const [resources, setResources] = useState([]);
+ const [categories, setCategories] = useState([]);
+ const [tags, setTags] = useState([]);
+ const [selectedResource, setSelectedResource] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const [authError, setAuthError] = useState(null);
+
+ // Login state
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+
+ // New/Edit resource form state
+ const [formData, setFormData] = useState({
+ name: '',
+ description: '',
+ url: '',
+ domain: '',
+ featured: false,
+ position: 0,
+ selectedCategories: [],
+ selectedTags: []
+ });
+
+ // Alert state
+ const [alert, setAlert] = useState({ show: false, message: '', type: '' });
+
+ // Check authentication on mount
+ useEffect(() => {
+ const checkAuth = async () => {
+ const { data: { session } } = await supabase.auth.getSession();
+ setIsAuthenticated(!!session);
+
+ if (session) {
+ fetchAllData();
+ } else {
+ setIsLoading(false);
+ }
+ };
+
+ checkAuth();
+ }, []);
+
+ // Login handler
+ const handleLogin = async (e) => {
+ e.preventDefault();
+ setIsLoading(true);
+ setAuthError(null);
+
+ try {
+ const { data, error } = await supabase.auth.signInWithPassword({
+ email,
+ password
+ });
+
+ if (error) throw error;
+
+ setIsAuthenticated(true);
+ fetchAllData();
+ } catch (error) {
+ console.error('Error logging in:', error);
+ setAuthError(error.message);
+ setIsLoading(false);
+ }
+ };
+
+ // Logout handler
+ const handleLogout = async () => {
+ await supabase.auth.signOut();
+ setIsAuthenticated(false);
+ };
+
+ // Fetch all required data from Supabase
+ const fetchAllData = async () => {
+ setIsLoading(true);
+ try {
+ // Fetch resources
+ const { data: resourcesData, error: resourcesError } = await supabase
+ .from('resources')
+ .select('*')
+ .order('position');
+
+ if (resourcesError) throw resourcesError;
+
+ // Fetch categories
+ const { data: categoriesData, error: categoriesError } = await supabase
+ .from('categories')
+ .select('*')
+ .order('name');
+
+ if (categoriesError) throw categoriesError;
+
+ // Fetch tags
+ const { data: tagsData, error: tagsError } = await supabase
+ .from('tags')
+ .select('*')
+ .order('name');
+
+ if (tagsError) throw tagsError;
+
+ // Fetch resource-category associations
+ const { data: resourceCategories, error: rcError } = await supabase
+ .from('resource_categories')
+ .select('*');
+
+ if (rcError) throw rcError;
+
+ // Fetch resource-tag associations
+ const { data: resourceTags, error: rtError } = await supabase
+ .from('resource_tags')
+ .select('*');
+
+ if (rtError) throw rtError;
+
+ // Enhance resources with their associated categories and tags
+ const enhancedResources = resourcesData.map(resource => {
+ const resourceCats = resourceCategories
+ .filter(rc => rc.resource_id === resource.id)
+ .map(rc => rc.category_id);
+
+ const resourceTs = resourceTags
+ .filter(rt => rt.resource_id === resource.id)
+ .map(rt => rt.tag_id);
+
+ return {
+ ...resource,
+ categoryIds: resourceCats,
+ tagIds: resourceTs
+ };
+ });
+
+ // Update state
+ setResources(enhancedResources);
+ setCategories(categoriesData);
+ setTags(tagsData);
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ showAlert(`Error: ${error.message}`, 'error');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // Handle resource selection
+ const handleSelectResource = (resource) => {
+ setSelectedResource(resource);
+ setFormData({
+ name: resource.name || '',
+ description: resource.description || '',
+ url: resource.url || '',
+ domain: resource.domain || '',
+ featured: resource.featured || false,
+ position: resource.position || 0,
+ selectedCategories: resource.categoryIds || [],
+ selectedTags: resource.tagIds || []
+ });
+ };
+
+ // Handle form input changes
+ const handleInputChange = (e) => {
+ const { name, value, type, checked } = e.target;
+ setFormData({
+ ...formData,
+ [name]: type === 'checkbox' ? checked : value
+ });
+ };
+
+ // Handle category selection changes
+ const handleCategoryChange = (categoryId) => {
+ setFormData(prevData => {
+ const selectedCategories = [...prevData.selectedCategories];
+
+ if (selectedCategories.includes(categoryId)) {
+ // Remove category if already selected
+ return {
+ ...prevData,
+ selectedCategories: selectedCategories.filter(id => id !== categoryId)
+ };
+ } else {
+ // Add category if not already selected
+ return {
+ ...prevData,
+ selectedCategories: [...selectedCategories, categoryId]
+ };
+ }
+ });
+ };
+
+ // Handle tag selection changes
+ const handleTagChange = (tagId) => {
+ setFormData(prevData => {
+ const selectedTags = [...prevData.selectedTags];
+
+ if (selectedTags.includes(tagId)) {
+ // Remove tag if already selected
+ return {
+ ...prevData,
+ selectedTags: selectedTags.filter(id => id !== tagId)
+ };
+ } else {
+ // Add tag if not already selected
+ return {
+ ...prevData,
+ selectedTags: [...selectedTags, tagId]
+ };
+ }
+ });
+ };
+
+ // Clear form and selected resource
+ const handleClearForm = () => {
+ setSelectedResource(null);
+ setFormData({
+ name: '',
+ description: '',
+ url: '',
+ domain: '',
+ featured: false,
+ position: resources.length + 1,
+ selectedCategories: [],
+ selectedTags: []
+ });
+ };
+
+ // Show alert message
+ const showAlert = (message, type = 'success') => {
+ setAlert({ show: true, message, type });
+ setTimeout(() => {
+ setAlert({ show: false, message: '', type: '' });
+ }, 5000);
+ };
+
+ // Save resource changes
+ const handleSaveResource = async (e) => {
+ e.preventDefault();
+ setIsLoading(true);
+
+ try {
+ const resourceData = {
+ name: formData.name,
+ description: formData.description,
+ url: formData.url,
+ domain: formData.domain,
+ featured: formData.featured,
+ position: formData.position,
+ updated_at: new Date().toISOString()
+ };
+
+ let resourceId;
+
+ if (selectedResource) {
+ // Update existing resource
+ const { error } = await supabase
+ .from('resources')
+ .update(resourceData)
+ .eq('id', selectedResource.id);
+
+ if (error) throw error;
+ resourceId = selectedResource.id;
+
+ // Delete existing category and tag associations
+ await supabase
+ .from('resource_categories')
+ .delete()
+ .eq('resource_id', resourceId);
+
+ await supabase
+ .from('resource_tags')
+ .delete()
+ .eq('resource_id', resourceId);
+
+ showAlert(`Resource "${formData.name}" updated successfully!`);
+ } else {
+ // Add new resource
+ resourceData.created_at = new Date().toISOString();
+
+ const { data, error } = await supabase
+ .from('resources')
+ .insert(resourceData)
+ .select();
+
+ if (error) throw error;
+ resourceId = data[0].id;
+
+ showAlert(`Resource "${formData.name}" created successfully!`);
+ }
+
+ // Add category associations
+ if (formData.selectedCategories.length > 0) {
+ const categoryAssociations = formData.selectedCategories.map(categoryId => ({
+ resource_id: resourceId,
+ category_id: categoryId
+ }));
+
+ const { error: categoryError } = await supabase
+ .from('resource_categories')
+ .insert(categoryAssociations);
+
+ if (categoryError) throw categoryError;
+ }
+
+ // Add tag associations
+ if (formData.selectedTags.length > 0) {
+ const tagAssociations = formData.selectedTags.map(tagId => ({
+ resource_id: resourceId,
+ tag_id: tagId
+ }));
+
+ const { error: tagError } = await supabase
+ .from('resource_tags')
+ .insert(tagAssociations);
+
+ if (tagError) throw tagError;
+ }
+
+ // Refresh data
+ fetchAllData();
+ handleClearForm();
+ } catch (error) {
+ console.error('Error saving resource:', error);
+ showAlert(`Error: ${error.message}`, 'error');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // Delete resource
+ const handleDeleteResource = async (resourceId, resourceName) => {
+ if (!window.confirm(`Are you sure you want to delete "${resourceName}"?`)) {
+ return;
+ }
+
+ setIsLoading(true);
+
+ try {
+ // Delete associated records first (foreign key constraints)
+ await supabase
+ .from('resource_categories')
+ .delete()
+ .eq('resource_id', resourceId);
+
+ await supabase
+ .from('resource_tags')
+ .delete()
+ .eq('resource_id', resourceId);
+
+ // Delete the resource
+ const { error } = await supabase
+ .from('resources')
+ .delete()
+ .eq('id', resourceId);
+
+ if (error) throw error;
+
+ showAlert(`Resource "${resourceName}" deleted successfully!`);
+
+ // Refresh data
+ fetchAllData();
+
+ // Clear form if the deleted resource was selected
+ if (selectedResource && selectedResource.id === resourceId) {
+ handleClearForm();
+ }
+ } catch (error) {
+ console.error('Error deleting resource:', error);
+ showAlert(`Error: ${error.message}`, 'error');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // Create new category
+ const handleCreateCategory = async () => {
+ const categoryName = prompt('Enter the new category name:');
+ if (!categoryName) return;
+
+ const emoji = prompt('Enter an emoji for this category:');
+ if (!emoji) return;
+
+ setIsLoading(true);
+
+ try {
+ const { data, error } = await supabase
+ .from('categories')
+ .insert({
+ name: categoryName,
+ emoji: emoji,
+ created_at: new Date().toISOString()
+ })
+ .select();
+
+ if (error) throw error;
+
+ showAlert(`Category "${categoryName}" created successfully!`);
+ fetchAllData();
+ } catch (error) {
+ console.error('Error creating category:', error);
+ showAlert(`Error: ${error.message}`, 'error');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // Create new tag
+ const handleCreateTag = async () => {
+ const tagName = prompt('Enter the new tag name:');
+ if (!tagName) return;
+
+ setIsLoading(true);
+
+ try {
+ const { data, error } = await supabase
+ .from('tags')
+ .insert({
+ name: tagName,
+ created_at: new Date().toISOString()
+ })
+ .select();
+
+ if (error) throw error;
+
+ showAlert(`Tag "${tagName}" created successfully!`);
+ fetchAllData();
+ } catch (error) {
+ console.error('Error creating tag:', error);
+ showAlert(`Error: ${error.message}`, 'error');
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ // Render loading spinner
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ // Render login form if not authenticated
+ if (!isAuthenticated) {
+ return (
+
+
+
Admin Login
+ {authError &&
{authError}
}
+
+
+
+ );
+ }
+
+ // Main admin panel UI
+ return (
+
+ {/* Header */}
+
+ Resources Admin Panel
+ Logout
+
+
+ {/* Alert message */}
+ {alert.show && (
+
+ {alert.message}
+
+ )}
+
+
+ {/* Resources list sidebar */}
+
+
+
Resources
+
+ + New Resource
+
+
+
+ {resources.map(resource => (
+
handleSelectResource(resource)}
+ >
+
{resource.name}
+
+ {
+ e.stopPropagation();
+ handleDeleteResource(resource.id, resource.name);
+ }}
+ className="delete-button"
+ title="Delete resource"
+ >
+ 🗑️
+
+
+
+ ))}
+
+
+
+ {/* Resource edit form */}
+
+
{selectedResource ? 'Edit Resource' : 'Add New Resource'}
+
+
+
+
+ );
+};
+
+export default AdminPanel;
\ No newline at end of file
diff --git a/src/components/Admin/AdminRoute.js b/src/components/Admin/AdminRoute.js
new file mode 100644
index 0000000..84da411
--- /dev/null
+++ b/src/components/Admin/AdminRoute.js
@@ -0,0 +1,57 @@
+// src/components/Admin/AdminRoute.jsx
+import React, { useState, useEffect } from 'react';
+import { Navigate } from 'react-router-dom';
+import { supabase } from '../../lib/supabase';
+import AdminPanel from './AdminPanel';
+
+// This component protects the admin route by checking authentication
+const AdminRoute = () => {
+ const [isAuthenticated, setIsAuthenticated] = useState(null);
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const checkAuth = async () => {
+ try {
+ const { data: { session } } = await supabase.auth.getSession();
+ setIsAuthenticated(!!session);
+ } catch (error) {
+ console.error('Error checking auth status:', error);
+ setIsAuthenticated(false);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ checkAuth();
+
+ // Listen for auth changes
+ const { data: { subscription } } = supabase.auth.onAuthStateChange(
+ (_event, session) => {
+ setIsAuthenticated(!!session);
+ }
+ );
+
+ return () => {
+ subscription.unsubscribe();
+ };
+ }, []);
+
+ if (isLoading) {
+ return (
+
+ );
+ }
+
+ // If not authenticated, redirect to home page
+ if (isAuthenticated === false) {
+ return ;
+ }
+
+ // If authenticated, render the admin panel
+ return ;
+};
+
+export default AdminRoute;
\ No newline at end of file