From 597f859e08c023771f678b357cecc79a7a0ec54d Mon Sep 17 00:00:00 2001
From: alphaeusmote <41258468-alphaeusmote@users.noreply.replit.com>
Date: Wed, 9 Apr 2025 00:47:22 +0000
Subject: [PATCH] Enhance theme switching to handle missing context
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 705f2157-ef97-4fbd-89e4-8c7f2ecaea90
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7ed01c5f-a82d-405a-b728-b2e3d127c60c/70b9c0b1-a5f0-4a27-9a6a-5bb48b9d90b1.jpg
---
client/src/components/theme-toggle.tsx | 18 +++++++
client/src/hooks/use-theme.tsx | 61 ++++++++++++++++++++-
client/src/pages/settings-page.tsx | 74 +++++++++++++++++++++-----
3 files changed, 137 insertions(+), 16 deletions(-)
diff --git a/client/src/components/theme-toggle.tsx b/client/src/components/theme-toggle.tsx
index 60fa977..8bcce77 100644
--- a/client/src/components/theme-toggle.tsx
+++ b/client/src/components/theme-toggle.tsx
@@ -9,7 +9,25 @@ import {
} from "@/components/ui/dropdown-menu";
import { useTheme } from "@/hooks/use-theme";
+// Fallback toggle without context dependency
export function ThemeToggle() {
+ // Try/catch block to handle possible context errors
+ try {
+ return ;
+ } catch (error) {
+ console.error("Theme context error:", error);
+ // Fallback rendering without context
+ return (
+
+ );
+ }
+}
+
+// Component that uses the theme context
+function ThemeToggleWithContext() {
const { theme, setTheme } = useTheme();
return (
diff --git a/client/src/hooks/use-theme.tsx b/client/src/hooks/use-theme.tsx
index ba42e4e..4c242d5 100644
--- a/client/src/hooks/use-theme.tsx
+++ b/client/src/hooks/use-theme.tsx
@@ -59,8 +59,65 @@ export function ThemeProvider({
export const useTheme = (): ThemeContextType => {
const context = useContext(ThemeContext);
- if (context === undefined)
- throw new Error('useTheme must be used within a ThemeProvider');
+ if (context === undefined) {
+ // Fallback implementation that doesn't rely on context
+ // This prevents crashes but won't sync across components
+ const storageKey = 'ad-management-theme';
+ const defaultTheme = 'system';
+
+ // Create a fallback state using localStorage
+ const getThemeFromStorage = (): Theme => {
+ try {
+ const storedTheme = localStorage.getItem(storageKey);
+ return (storedTheme as Theme) || defaultTheme;
+ } catch (e) {
+ return defaultTheme;
+ }
+ };
+
+ const currentTheme = getThemeFromStorage();
+
+ const applyThemeToDOM = (newTheme: Theme) => {
+ try {
+ const root = window.document.documentElement;
+ root.classList.remove('light', 'dark');
+
+ if (newTheme === 'system') {
+ const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
+ ? 'dark'
+ : 'light';
+ root.classList.add(systemTheme);
+ } else {
+ root.classList.add(newTheme);
+ }
+ } catch (e) {
+ console.error('Error applying theme to DOM:', e);
+ }
+ };
+
+ // Apply the theme immediately for this component
+ applyThemeToDOM(currentTheme);
+
+ // Return a fallback implementation
+ return {
+ theme: currentTheme,
+ setTheme: (newTheme: Theme) => {
+ try {
+ localStorage.setItem(storageKey, newTheme);
+ applyThemeToDOM(newTheme);
+
+ // We can't update state here because we're not in a React component
+ // but we can apply the theme directly to the DOM
+ console.warn(
+ 'Theme changed outside of ThemeProvider context. ' +
+ 'This change won\'t be synced between components.'
+ );
+ } catch (e) {
+ console.error('Error setting theme:', e);
+ }
+ }
+ };
+ }
return context;
};
\ No newline at end of file
diff --git a/client/src/pages/settings-page.tsx b/client/src/pages/settings-page.tsx
index ac1cdc8..c7cf6d2 100644
--- a/client/src/pages/settings-page.tsx
+++ b/client/src/pages/settings-page.tsx
@@ -1,3 +1,4 @@
+import { useState, useEffect } from "react";
import { DashboardLayout } from "@/layouts/dashboard-layout";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Switch } from "@/components/ui/switch";
@@ -14,6 +15,64 @@ import {
SelectValue
} from "@/components/ui/select";
import { Separator } from "@/components/ui/separator";
+import { Moon, Sun, Laptop } from "lucide-react";
+
+// Safe theme selector that doesn't throw errors if ThemeProvider is missing
+function ThemeSelector() {
+ const [currentTheme, setCurrentTheme] = useState(() => {
+ // Read from localStorage or default to system
+ return localStorage.getItem("ad-management-theme") || "system";
+ });
+
+ const handleThemeChange = (value: string) => {
+ setCurrentTheme(value);
+
+ try {
+ // Handle theme change manually if context is missing
+ localStorage.setItem("ad-management-theme", value);
+
+ const root = window.document.documentElement;
+ root.classList.remove("light", "dark");
+
+ if (value === "system") {
+ const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+ root.classList.add(systemTheme);
+ } else {
+ root.classList.add(value);
+ }
+ } catch (error) {
+ console.error("Error changing theme:", error);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
export default function SettingsPage() {
return (
@@ -43,20 +102,7 @@ export default function SettingsPage() {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+