From a93e2aa863b078180f688f7fa20b0c69d38a2d99 Mon Sep 17 00:00:00 2001 From: kayela Date: Wed, 7 Jan 2026 11:01:54 -0600 Subject: [PATCH] Theme provider --- src/components/AdminSidebar.js | 80 ++++++++++++++++++++++++---------- src/index.js | 10 ++++- src/layouts/AdminLayout.js | 5 ++- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/src/components/AdminSidebar.js b/src/components/AdminSidebar.js index fc70405..ffc10bf 100644 --- a/src/components/AdminSidebar.js +++ b/src/components/AdminSidebar.js @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; +import { useTheme } from 'next-themes'; import { useAuth } from '../context/AuthContext'; import api from '../utils/api'; import { Badge } from './ui/badge'; @@ -23,16 +24,20 @@ import { HardDrive, Repeat, Heart, + Sun, + Moon, } from 'lucide-react'; const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { const location = useLocation(); const navigate = useNavigate(); const { user, logout } = useAuth(); + const { theme, setTheme } = useTheme(); const [pendingCount, setPendingCount] = useState(0); const [storageUsed, setStorageUsed] = useState(0); const [storageLimit, setStorageLimit] = useState(0); const [storagePercentage, setStoragePercentage] = useState(0); + const isDark = theme === 'dark'; // Fetch pending approvals count useEffect(() => { @@ -86,6 +91,10 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { navigate('/login'); }; + const handleThemeToggle = () => { + setTheme(isDark ? 'light' : 'dark'); + }; + const navItems = [ { name: 'Dashboard', @@ -211,7 +220,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { > {/* Active border */} {active && !item.disabled && ( -
+
)} @@ -225,7 +234,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { )} {item.badge > 0 && !item.disabled && ( - + {item.badge} )} @@ -234,7 +243,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* Badge when collapsed */} {!isOpen && item.badge > 0 && !item.disabled && ( -
+
{item.badge}
)} @@ -242,7 +251,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* Tooltip when collapsed */} {!isOpen && ( -
+
{item.name} {item.badge > 0 && ` (${item.badge})`}
@@ -274,10 +283,10 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { /> {isOpen && (
-

+

Admin

-

+

View Public Site

@@ -289,11 +298,11 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { aria-label={isOpen ? 'Collapse sidebar' : 'Expand sidebar'} > {isMobile ? ( - + ) : isOpen ? ( - + ) : ( - + )}
@@ -306,7 +315,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* MEMBERSHIP Section */} {isOpen && (
-

+

Membership

@@ -320,7 +329,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* FINANCIALS Section */} {isOpen && (
-

+

Financials

@@ -334,7 +343,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* EVENTS & MEDIA Section */} {isOpen && (
-

+

Events & Media

@@ -347,7 +356,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* DOCUMENTATION Section */} {isOpen && (
-

+

Documentation

@@ -375,10 +384,10 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {user.first_name?.[0]}{user.last_name?.[0]}
-

+

{user.first_name} {user.last_name}

-

+

{user.role}

@@ -388,13 +397,40 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
)} + {/* Theme Toggle */} +
+ + {!isOpen && ( +
+ {isDark ? 'Light mode' : 'Dark mode'} +
+ )} +
+ {/* Storage Usage Widget */}
{isOpen ? (
- Storage Usage - {storagePercentage}% + Storage Usage + {storagePercentage}%
{ style={{ width: `${storagePercentage}%` }} />
-

+

{formatBytes(storageUsed)} / {formatBytes(storageLimit)}

@@ -414,13 +450,13 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
90 ? 'text-red-500' : storagePercentage > 75 ? 'text-yellow-500' : - 'text-[#664fa3]' + 'text-muted-foreground' }`} /> {storagePercentage > 75 && (
)} {/* Tooltip */} -
+
Storage: {storagePercentage}%
@@ -433,7 +469,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { onClick={handleLogout} className={` flex items-center gap-3 px-4 py-3 rounded-lg w-full - text-[#ff9e77] hover:bg-[#ff9e77]/10 transition-colors + text-accent hover:bg-accent/10 transition-colors ${!isOpen && 'justify-center'} `} > @@ -444,7 +480,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => { {/* Logout tooltip when collapsed */} {!isOpen && (
-
+
Logout
diff --git a/src/index.js b/src/index.js index 79282d0..a4a0d50 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; +import { ThemeProvider } from 'next-themes'; import '@fontsource/fraunces/600.css'; import '@fontsource/dm-sans/400.css'; import '@fontsource/dm-sans/700.css'; @@ -9,6 +10,13 @@ import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + + + ); diff --git a/src/layouts/AdminLayout.js b/src/layouts/AdminLayout.js index 668f6b9..a93df83 100644 --- a/src/layouts/AdminLayout.js +++ b/src/layouts/AdminLayout.js @@ -1,9 +1,12 @@ import React, { useState, useEffect } from 'react'; +import { useTheme } from 'next-themes'; import AdminSidebar from '../components/AdminSidebar'; const AdminLayout = ({ children }) => { const [sidebarOpen, setSidebarOpen] = useState(true); const [isMobile, setIsMobile] = useState(false); + const { theme } = useTheme(); + const isDark = theme === 'dark'; // Initialize sidebar state from localStorage useEffect(() => { @@ -43,7 +46,7 @@ const AdminLayout = ({ children }) => { }; return ( -
+
{/* Sidebar */}