From a7b6b78890792b79ec51f962abe4c4b1b5afd7c4 Mon Sep 17 00:00:00 2001 From: Atul Gunjal Date: Wed, 9 Apr 2025 11:34:27 +0530 Subject: [PATCH] applied dark mode --- package-lock.json | 21 ++++++ package.json | 2 + postcss.config.mjs | 3 +- src/app/client-layout.js | 79 +++++++++++++++++++++ src/app/components/Navbar.jsx | 120 ++++++++++++++++++++++++++++---- src/app/components/Sidebar.jsx | 77 ++++++++++++++------ src/app/context/ThemeContext.js | 10 +++ src/app/globals.css | 34 ++++++++- src/app/layout.js | 17 ++--- 9 files changed, 314 insertions(+), 49 deletions(-) create mode 100644 src/app/client-layout.js create mode 100644 src/app/context/ThemeContext.js diff --git a/package-lock.json b/package-lock.json index 38d56f9..867e577 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,9 +12,11 @@ "appwrite": "^17.0.1", "lucide-react": "^0.487.0", "next": "15.2.4", + "next-themes": "^0.4.6", "postcss": "^8.5.3", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-icons": "^5.5.0", "tailwindcss": "^4.1.3" }, "devDependencies": { @@ -4311,6 +4313,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", @@ -4701,6 +4713,15 @@ "react": "^19.1.0" } }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index f985186..f36573f 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,11 @@ "appwrite": "^17.0.1", "lucide-react": "^0.487.0", "next": "15.2.4", + "next-themes": "^0.4.6", "postcss": "^8.5.3", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-icons": "^5.5.0", "tailwindcss": "^4.1.3" }, "devDependencies": { diff --git a/postcss.config.mjs b/postcss.config.mjs index bc9198c..a7475b7 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,5 +1,6 @@ const config = { - plugins: { + darkMode: ['class', '[data-theme="dark"]'], + plugins: { "@tailwindcss/postcss": {}, }, }; diff --git a/src/app/client-layout.js b/src/app/client-layout.js new file mode 100644 index 0000000..5f1dafa --- /dev/null +++ b/src/app/client-layout.js @@ -0,0 +1,79 @@ +'use client'; +import { useState, useEffect } from "react"; +import { account } from "./lib/appwrite"; +import { useRouter } from "next/navigation"; +import Sidebar from "./components/Sidebar"; +import Navbar from "./components/Navbar"; +import { Menu } from 'lucide-react'; + +export default function ClientLayout({ children }) { + const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(false); + const [isMobileOpen, setIsMobileOpen] = useState(false); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [loading, setLoading] = useState(true); + const router = useRouter(); + + useEffect(() => { + const checkAuth = async () => { + try { + await account.get(); + setIsLoggedIn(true); + } catch (error) { + setIsLoggedIn(false); + router.push('/login'); + } finally { + setLoading(false); + } + }; + checkAuth(); + }, [router]); + + const toggleMobileSidebar = () => { + setIsMobileOpen(!isMobileOpen); + }; + + if (loading) { + return
Loading...
; + } + + if (!isLoggedIn) { + return ( +
+
+ {children} +
+
+ ); + } + + return ( +
+ {/* Mobile Toggle Button (outside sidebar) */} + + + + +
+ setIsSidebarCollapsed(!isSidebarCollapsed)} + /> + +
+ {children} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/app/components/Navbar.jsx b/src/app/components/Navbar.jsx index a538cb3..f21c804 100644 --- a/src/app/components/Navbar.jsx +++ b/src/app/components/Navbar.jsx @@ -1,34 +1,126 @@ 'use client'; +import { useState, useEffect } from "react"; import { account } from "../lib/appwrite"; -import { useRouter } from 'next/navigation'; -import { LogOut } from 'lucide-react'; +import { useRouter } from "next/navigation"; +import { FaUserCircle, FaMoon, FaSun } from "react-icons/fa"; +import { LogOut, Menu } from "lucide-react"; -export default function Navbar() { +export default function Navbar({ toggleSidebar }) { const router = useRouter(); + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const [user, setUser] = useState(null); + const [darkMode, setDarkMode] = useState(false); + + // Initialize dark mode from localStorage or system preference + useEffect(() => { + const savedMode = localStorage.getItem('darkMode'); + const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + + if (savedMode !== null) { + setDarkMode(savedMode === 'true'); + } else if (systemPrefersDark) { + setDarkMode(true); + } + }, []); + + // Apply dark mode class to document element + useEffect(() => { + if (darkMode) { + document.documentElement.classList.add('dark'); + localStorage.setItem('darkMode', 'true'); + } else { + document.documentElement.classList.remove('dark'); + localStorage.setItem('darkMode', 'false'); + } + }, [darkMode]); + + // Toggle dark mode + const toggleDarkMode = () => { + setDarkMode(!darkMode); + }; + + // Fetch current user details + useEffect(() => { + const getUser = async () => { + try { + const userData = await account.get(); + setUser(userData); + } catch (error) { + console.error("Error fetching user:", error); + } + }; + getUser(); + }, []); const handleLogout = async () => { try { - await account.deleteSession('current'); - router.push('/login'); + await account.deleteSession("current"); + router.push("/login"); } catch (error) { - console.error('Logout failed:', error); + console.error("Logout failed:", error); } }; return ( -