diff --git a/src/assets/darkmode-removebg.png b/src/assets/darkmode-removebg.png new file mode 100644 index 0000000..4f8aaf5 Binary files /dev/null and b/src/assets/darkmode-removebg.png differ diff --git a/src/assets/darkmode.png b/src/assets/darkmode.png new file mode 100644 index 0000000..62afc86 Binary files /dev/null and b/src/assets/darkmode.png differ diff --git a/src/assets/lightmode-removebg.png b/src/assets/lightmode-removebg.png new file mode 100644 index 0000000..ede399f Binary files /dev/null and b/src/assets/lightmode-removebg.png differ diff --git a/src/assets/lightmode.png b/src/assets/lightmode.png new file mode 100644 index 0000000..532cec9 Binary files /dev/null and b/src/assets/lightmode.png differ diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index 11b1c1b..9f3bc6e 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -1,7 +1,9 @@ -import { useState } from "react"; import { Github, Info, ShieldCheck, ScrollText, Star, UsersIcon, ArrowUpRight } from "lucide-react"; import { Link } from "react-router-dom"; -import logoF from "../assets/logo.png"; +// Update the logo imports +import logoLight from '../assets/lightmode-removebg.png'; +import logoDark from '../assets/darkmode-removebg.png'; +import { useState, useEffect } from 'react'; const Footer = () => { const currentYear = new Date().getFullYear(); @@ -9,6 +11,52 @@ const Footer = () => { const [feedbackText, setFeedbackText] = useState(""); const [message, setMessage] = useState(""); + // Updated dark mode detection state with localStorage check + const [isDarkMode, setIsDarkMode] = useState(() => { + // Check localStorage first + const savedTheme = localStorage.getItem('theme'); + if (savedTheme) { + return savedTheme === 'dark'; + } + // If no saved theme, check system preference + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + return true; + } + // Check DOM as fallback + return document.documentElement.classList.contains('dark'); + }); + + // Updated effect to listen for dark mode changes + useEffect(() => { + // Function to update dark mode state + const updateDarkMode = () => { + const isDark = document.documentElement.classList.contains('dark'); + setIsDarkMode(isDark); + localStorage.setItem('theme', isDark ? 'dark' : 'light'); + }; + + // Initial check + updateDarkMode(); + + // Set up observer for class changes + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.attributeName === 'class') { + updateDarkMode(); + } + }); + }); + + // Start observing + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'], + }); + + // Clean up + return () => observer.disconnect(); + }, []); + const socialLinks = [ { name: "GitHub", @@ -55,7 +103,11 @@ const Footer = () => { {/* Logo & description */}
- Civix Logo + Civix Logo

Empowering citizens through technology. Stay informed, make better decisions, and engage with civic life through our innovative platform. diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx index b911c01..b9bf33f 100644 --- a/src/components/Navbar.jsx +++ b/src/components/Navbar.jsx @@ -1,11 +1,24 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { useNavigate, Link, useLocation } from 'react-router-dom'; -import Switch from '../DarkModeToggle'; -import { jwtDecode } from 'jwt-decode'; -import { useAuth } from '@clerk/clerk-react'; -import logo from '../assets/logo.png'; -import { title } from 'process'; -import { Info, Phone, Users, User, LogOut, Shield, LayoutDashboard, BookOpen, Menu, X, AlertTriangle,Vote } from 'lucide-react'; +import React, { useState, useEffect, useRef } from "react"; +import { useNavigate, Link, useLocation } from "react-router-dom"; +import Switch from "../DarkModeToggle"; +import { jwtDecode } from "jwt-decode"; +import { useAuth } from "@clerk/clerk-react"; +// Updated logo imports +import logoLight from "../assets/lightmode-removebg.png"; +import logoDark from "../assets/darkmode-removebg.png"; +import { + Info, + Phone, + Users, + Vote, + X, + Menu, + User, + Shield, + LayoutDashboard, + AlertTriangle, + LogOut, +} from "lucide-react"; const Navbar = () => { const navigate = useNavigate(); @@ -15,6 +28,52 @@ const Navbar = () => { const rightDropdownRef = useRef(null); const { isSignedIn, signOut } = useAuth(); + // Updated dark mode detection state with localStorage check + const [isDarkMode, setIsDarkMode] = useState(() => { + // Check localStorage first + const savedTheme = localStorage.getItem("theme"); + if (savedTheme) { + return savedTheme === "dark"; + } + // If no saved theme, check system preference + if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + return true; + } + // Check DOM as fallback + return document.documentElement.classList.contains("dark"); + }); + + // Updated effect to listen for dark mode changes + useEffect(() => { + // Function to update dark mode state + const updateDarkMode = () => { + const isDark = document.documentElement.classList.contains("dark"); + setIsDarkMode(isDark); + localStorage.setItem("theme", isDark ? "dark" : "light"); + }; + + // Initial check + updateDarkMode(); + + // Set up observer for class changes + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.attributeName === "class") { + updateDarkMode(); + } + }); + }); + + // Start observing + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["class"], + }); + + // Clean up + return () => observer.disconnect(); + }, []); + const handleNav = (cb) => { setMobileMenuOpen(false); if (cb) cb(); @@ -22,7 +81,7 @@ const Navbar = () => { const handleLogout = async () => { if (signOut) { - await signOut(); + await signOut(); } localStorage.removeItem("token"); window.dispatchEvent(new Event("storage-update")); @@ -31,51 +90,58 @@ const Navbar = () => { }; const handleSOSClick = () => { - navigate('/sos'); + navigate("/sos"); }; useEffect(() => { const handleClickOutside = (event) => { - if (rightDropdownRef.current && !rightDropdownRef.current.contains(event.target)) { + if ( + rightDropdownRef.current && + !rightDropdownRef.current.contains(event.target) + ) { setRightDropdownOpen(false); } }; - document.addEventListener('mousedown', handleClickOutside); + document.addEventListener("mousedown", handleClickOutside); return () => { - document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener("mousedown", handleClickOutside); }; }, []); useEffect(() => { if (!mobileMenuOpen) return; const onKeyDown = (e) => { - if (e.key === 'Escape') setMobileMenuOpen(false); + if (e.key === "Escape") setMobileMenuOpen(false); }; - window.addEventListener('keydown', onKeyDown); - return () => window.removeEventListener('keydown', onKeyDown); + window.addEventListener("keydown", onKeyDown); + return () => window.removeEventListener("keydown", onKeyDown); }, [mobileMenuOpen]); useEffect(() => { if (!mobileMenuOpen) return; const onClick = (e) => { - if (e.target.closest('#mobile-nav-panel') || e.target.closest('#mobile-nav-toggle')) return; + if ( + e.target.closest("#mobile-nav-panel") || + e.target.closest("#mobile-nav-toggle") + ) + return; setMobileMenuOpen(false); }; - document.addEventListener('mousedown', onClick); - return () => document.removeEventListener('mousedown', onClick); + document.addEventListener("mousedown", onClick); + return () => document.removeEventListener("mousedown", onClick); }, [mobileMenuOpen]); - const token = localStorage.getItem('token'); + const token = localStorage.getItem("token"); let isAdmin = false; try { if (token) { const decoded = jwtDecode(token); - isAdmin = decoded.role === 'admin'; + isAdmin = decoded.role === "admin"; } } catch (err) { - console.error('Invalid token'); + console.error("Invalid token"); } const navLinks = [ @@ -102,148 +168,156 @@ const Navbar = () => { ]; return ( -

-
-
- -
- -
+
+
+
+ +
- + - + +
+ +
+ +
-
- +
-
- -
- -
- - - {rightDropdownOpen && ( -
-
- + {rightDropdownOpen && ( +
+
+
- + {!(isSignedIn || token) ? ( ) : ( <> -
- +
- - )}
- )} -
+
+ )}
@@ -255,11 +329,10 @@ const Navbar = () => { onClick={() => setMobileMenuOpen(false)} aria-hidden="true" /> - -
-