From b5ddd1f70f8fbfc58ae890ddc6250a116dd6fcf9 Mon Sep 17 00:00:00 2001 From: ARUN N G Date: Thu, 19 Feb 2026 21:34:06 +0530 Subject: [PATCH] adding white theme --- App.tsx | 5 + components/layout/DashboardLayout.tsx | 44 ++++--- contexts/ThemeContext.tsx | 57 ++++++++ index.html | 75 ++++++++++- pages/SettingsPage.tsx | 181 ++++++++++++++++++++++++++ 5 files changed, 342 insertions(+), 20 deletions(-) create mode 100644 contexts/ThemeContext.tsx create mode 100644 pages/SettingsPage.tsx diff --git a/App.tsx b/App.tsx index 1edf701..31e13b8 100644 --- a/App.tsx +++ b/App.tsx @@ -10,6 +10,7 @@ import { AuthProvider } from "./contexts/AuthContext"; import { NotificationsProvider } from "./contexts/NotificationsContext"; import { ChatProvider } from "./contexts/ChatContext"; import { PaymentProvider } from "./contexts/PaymentContext"; +import { ThemeProvider } from "./contexts/ThemeContext"; import SplashPage from "./pages/SplashPage"; import LoginPage from "./pages/LoginPage"; @@ -20,6 +21,7 @@ import NotificationsPage from "./pages/NotificationsPage"; import ProfilePage from "./pages/ProfilePage"; import ChatPage from "./pages/ChatPage"; import DrinksPage from "./pages/DrinksPage"; +import SettingsPage from "./pages/SettingsPage"; import DashboardLayout from "./components/layout/DashboardLayout"; import ProtectedRoute from "./components/auth/ProtectedRoute"; @@ -27,6 +29,7 @@ import TargetCursor from "./components/common/TargetCursor"; const App: React.FC = () => { return ( + @@ -59,6 +62,7 @@ const App: React.FC = () => { } /> } /> } /> + } /> } /> @@ -68,6 +72,7 @@ const App: React.FC = () => { + ); }; diff --git a/components/layout/DashboardLayout.tsx b/components/layout/DashboardLayout.tsx index 6d8fc41..adb8e9c 100644 --- a/components/layout/DashboardLayout.tsx +++ b/components/layout/DashboardLayout.tsx @@ -2,11 +2,12 @@ import React from 'react'; // FIX: Use namespace import for react-router-dom to address potential module resolution issues. import * as ReactRouterDOM from 'react-router-dom'; -import { Home, CreditCard, History, Bell, User, Zap, ChevronsUpDown, LogOut, MessageSquare, Wine, Download, X } from 'lucide-react'; +import { Home, CreditCard, History, Bell, User, Zap, ChevronsUpDown, LogOut, MessageSquare, Wine, Download, X, Settings } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; import { useAuth } from '../../hooks/useAuth'; import { useNotifications } from '../../contexts/NotificationsContext'; import { useChat } from '../../contexts/ChatContext'; +import { useTheme } from '../../contexts/ThemeContext'; import ShinyText from '../common/ShinyText'; const navItems = [ @@ -19,12 +20,14 @@ const navItems = [ ]; const bottomNavItems = [ + { path: '/dashboard/settings', icon: Settings, label: 'Settings' }, { path: '/dashboard/profile', icon: User, label: 'Profile' } ]; const NavItem: React.FC<{ item: typeof navItems[0]; isMobile: boolean }> = ({ item, isMobile }) => { const { unreadCount: unreadNotificationsCount } = useNotifications(); const { unreadCount: unreadChatCount } = useChat(); + const { isDark } = useTheme(); const isNotificationsLink = item.label === 'Notifications'; const isChatLink = item.label === 'Chat'; const badgeCount = isNotificationsLink ? unreadNotificationsCount : (isChatLink ? unreadChatCount : 0); @@ -39,13 +42,15 @@ const NavItem: React.FC<{ item: typeof navItems[0]; isMobile: boolean }> = ({ it {({ isActive }) => (
{badgeCount > 0 && ( - + {badgeCount > 9 ? '9+' : badgeCount} )} @@ -73,8 +78,8 @@ const NavItem: React.FC<{ item: typeof navItems[0]; isMobile: boolean }> = ({ it to={item.path} className={({ isActive }) => `flex items-center px-3 py-2.5 rounded-md transition-colors duration-200 text-sm font-medium ${isActive - ? 'bg-zinc-800 text-white' - : 'text-gray-400 hover:text-white hover:bg-zinc-800/50' + ? (isDark ? 'bg-zinc-800 text-white' : 'bg-gray-200 text-gray-900') + : (isDark ? 'text-gray-400 hover:text-white hover:bg-zinc-800/50' : 'text-gray-500 hover:text-gray-900 hover:bg-gray-100') }` } > @@ -93,6 +98,7 @@ const NavItem: React.FC<{ item: typeof navItems[0]; isMobile: boolean }> = ({ it const DashboardLayout: React.FC = () => { const location = ReactRouterDOM.useLocation(); const { profile, logout } = useAuth(); + const { isDark } = useTheme(); const allNavItemsForMobile = [...navItems, ...bottomNavItems]; const [showDownloadBanner, setShowDownloadBanner] = React.useState(() => { // Check if banner was dismissed before @@ -101,30 +107,30 @@ const DashboardLayout: React.FC = () => { }); return ( -
+
{/* Sidebar for Desktop */} -
-
+
{ {/* Bottom Nav for Mobile */}
-
diff --git a/contexts/ThemeContext.tsx b/contexts/ThemeContext.tsx new file mode 100644 index 0000000..49a9966 --- /dev/null +++ b/contexts/ThemeContext.tsx @@ -0,0 +1,57 @@ +import React, { createContext, useState, useEffect, useContext, ReactNode } from 'react'; + +export type Theme = 'dark' | 'light'; + +interface ThemeContextType { + theme: Theme; + toggleTheme: () => void; + setTheme: (theme: Theme) => void; + isDark: boolean; +} + +const ThemeContext = createContext(undefined); + +const THEME_KEY = 'brocode_theme'; + +export const ThemeProvider = ({ children }: { children: ReactNode }) => { + const [theme, setThemeState] = useState(() => { + const saved = localStorage.getItem(THEME_KEY); + return (saved === 'light' || saved === 'dark') ? saved : 'dark'; + }); + + useEffect(() => { + localStorage.setItem(THEME_KEY, theme); + const root = document.documentElement; + if (theme === 'light') { + root.classList.add('light-theme'); + root.classList.remove('dark-theme'); + document.body.classList.remove('bg-black', 'text-gray-200'); + document.body.classList.add('bg-white', 'text-gray-800'); + } else { + root.classList.add('dark-theme'); + root.classList.remove('light-theme'); + document.body.classList.remove('bg-white', 'text-gray-800'); + document.body.classList.add('bg-black', 'text-gray-200'); + } + }, [theme]); + + const toggleTheme = () => { + setThemeState(prev => prev === 'dark' ? 'light' : 'dark'); + }; + + const setTheme = (newTheme: Theme) => { + setThemeState(newTheme); + }; + + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (!context) throw new Error('useTheme must be used within ThemeProvider'); + return context; +}; diff --git a/index.html b/index.html index 95f5258..a872f4a 100644 --- a/index.html +++ b/index.html @@ -75,6 +75,79 @@ .animate-star-movement-top { animation: star-movement-top linear infinite alternate; } + + /* ===== LIGHT THEME OVERRIDES ===== */ + .light-theme body { + background-color: #ffffff !important; + color: #1f2937 !important; + } + + .light-theme ::-webkit-scrollbar-track { + background: #f3f4f6; + } + + .light-theme ::-webkit-scrollbar-thumb { + background-color: #d1d5db; + border: 2px solid #f3f4f6; + } + + .light-theme ::-webkit-scrollbar-thumb:hover { + background-color: #9ca3af; + } + + /* Sidebar & nav backgrounds */ + .light-theme .bg-black { background-color: #ffffff !important; } + .light-theme .bg-\[black\] { background-color: #ffffff !important; } + .light-theme .bg-\[\#111111\] { background-color: #f9fafb !important; } + .light-theme .bg-\[\#111\] { background-color: #f3f4f6 !important; } + .light-theme .bg-\[\#0a0a0a\] { background-color: #f9fafb !important; } + .light-theme .bg-\[\#1C1C1C\] { background-color: #ffffff !important; box-shadow: 0 -1px 10px rgba(0,0,0,0.08) !important; } + + /* Zinc backgrounds */ + .light-theme .bg-zinc-900 { background-color: #f3f4f6 !important; } + .light-theme .bg-zinc-800 { background-color: #e5e7eb !important; } + .light-theme .bg-zinc-800\/50 { background-color: rgba(229, 231, 235, 0.5) !important; } + .light-theme .bg-zinc-900\/50 { background-color: rgba(243, 244, 246, 0.5) !important; } + + /* Text colors */ + .light-theme .text-white { color: #111827 !important; } + .light-theme .text-gray-200 { color: #374151 !important; } + .light-theme .text-gray-400 { color: #6b7280 !important; } + .light-theme .text-zinc-400 { color: #6b7280 !important; } + .light-theme .text-zinc-500 { color: #9ca3af !important; } + .light-theme .text-zinc-600 { color: #6b7280 !important; } + + /* Borders */ + .light-theme .border-zinc-800 { border-color: #e5e7eb !important; } + .light-theme .border-zinc-700 { border-color: #d1d5db !important; } + .light-theme .border-zinc-700\/80 { border-color: rgba(209, 213, 219, 0.8) !important; } + .light-theme .border-white\/5 { border-color: rgba(0, 0, 0, 0.06) !important; } + + /* Hover states */ + .light-theme .hover\:bg-zinc-800:hover { background-color: #e5e7eb !important; } + .light-theme .hover\:bg-zinc-800\/50:hover { background-color: rgba(229, 231, 235, 0.5) !important; } + .light-theme .hover\:text-white:hover { color: #111827 !important; } + .light-theme .hover\:text-zinc-300:hover { color: #374151 !important; } + + /* Active nav pill for mobile */ + .light-theme .bg-white.text-black { + background-color: #111827 !important; + color: #ffffff !important; + } + + /* Cards & panels */ + .light-theme .bg-black\/50 { background-color: rgba(255, 255, 255, 0.7) !important; } + + /* Border badges */ + .light-theme .border-\[\#1C1C1C\] { border-color: #ffffff !important; } + .light-theme .border-\[\#111\] { border-color: #f3f4f6 !important; } + + /* Dashed borders */ + .light-theme .border-dashed.border-zinc-700 { border-color: #d1d5db !important; } + .light-theme .border-dashed.border-zinc-800 { border-color: #d1d5db !important; } + + /* Group hover text */ + .light-theme .group-hover\:bg-zinc-800 { background-color: #e5e7eb !important; } - \ No newline at end of file + diff --git a/pages/SettingsPage.tsx b/pages/SettingsPage.tsx new file mode 100644 index 0000000..cfd6c63 --- /dev/null +++ b/pages/SettingsPage.tsx @@ -0,0 +1,181 @@ +import React from 'react'; +import { useTheme } from '../contexts/ThemeContext'; +import { Moon, Sun, ChevronRight, Palette, Shield, Bell, Info, ArrowLeft } from 'lucide-react'; +import { motion } from 'framer-motion'; +import * as ReactRouterDOM from 'react-router-dom'; +const { useNavigate } = ReactRouterDOM; + +const SettingsPage: React.FC = () => { + const { theme, toggleTheme, isDark } = useTheme(); + const navigate = useNavigate(); + + return ( +
+ {/* Header */} +
+ +
+

+ Settings +

+

+ Customize your experience +

+
+
+ + {/* Appearance Section */} +
+

+ Appearance +

+
+ {/* Theme Toggle */} +
+
+
+ {isDark ? : } +
+
+

Theme

+

+ {isDark ? 'Dark Mode' : 'Light Mode'} +

+
+
+ {/* Toggle Switch */} + +
+ + {/* Theme Preview */} +
+

+ Preview +

+
+ {/* Dark Preview */} + + {/* Light Preview */} + +
+
+
+
+ + {/* General Section */} +
+

+ General +

+
+ } + label="Notifications" + description="Manage alerts" + isDark={isDark} + onClick={() => navigate('/dashboard/notifications')} + /> + } + label="Privacy" + description="Account security" + isDark={isDark} + /> + } + label="About" + description="App version 2.0.0" + isDark={isDark} + /> +
+
+
+ ); +}; + +const SettingsRow: React.FC<{ + icon: React.ReactNode; + label: string; + description: string; + isDark: boolean; + onClick?: () => void; +}> = ({ icon, label, description, isDark, onClick }) => ( + +); + +export default SettingsPage;