11// Theme Toggle Functionality
22var ThemeToggle = {
3+ COOKIE_NAME : 'theme_preference' ,
4+ COOKIE_DAYS : 365 ,
5+
36 init : function ( ) {
4- console . log ( 'ThemeToggle: Initializing...' ) ;
5- var savedTheme = this . getSavedTheme ( ) ;
6- console . log ( 'ThemeToggle: Saved theme is' , savedTheme ) ;
7- this . applyTheme ( savedTheme ) ;
8- this . bindEvents ( ) ;
7+ var self = this ;
8+ this . isAuthenticated = this . checkAuthentication ( ) ;
9+
10+ if ( this . isAuthenticated ) {
11+ this . loadServerThemePreference ( function ( theme ) {
12+ self . applyTheme ( theme ) ;
13+ self . bindEvents ( ) ;
14+ } ) ;
15+ } else {
16+ var savedTheme = this . getSavedTheme ( ) ;
17+ this . applyTheme ( savedTheme ) ;
18+ this . bindEvents ( ) ;
19+ }
20+ } ,
21+
22+ checkAuthentication : function ( ) {
23+ var metaTag = document . querySelector ( 'meta[name="current-user"]' ) ;
24+ return metaTag && metaTag . getAttribute ( 'content' ) ;
25+ } ,
26+
27+ getCurrentUserId : function ( ) {
28+ var metaTag = document . querySelector ( 'meta[name="current-user"]' ) ;
29+ return metaTag ? metaTag . getAttribute ( 'content' ) : null ;
30+ } ,
31+
32+ loadServerThemePreference : function ( callback ) {
33+ var userId = this . getCurrentUserId ( ) ;
34+ if ( ! userId ) {
35+ callback ( this . getSystemTheme ( ) ) ;
36+ return ;
37+ }
38+
39+ var self = this ;
40+ fetch ( '/accounts/' + userId + '/theme_preference.json' , {
41+ method : 'GET' ,
42+ credentials : 'same-origin' ,
43+ headers : {
44+ 'Accept' : 'application/json'
45+ }
46+ } )
47+ . then ( function ( response ) {
48+ if ( ! response . ok ) {
49+ return callback ( self . getSystemTheme ( ) ) ;
50+ }
51+ return response . json ( ) ;
52+ } )
53+ . then ( function ( data ) {
54+ if ( data && data . theme_preference ) {
55+ callback ( data . theme_preference ) ;
56+ } else {
57+ callback ( self . getSystemTheme ( ) ) ;
58+ }
59+ } )
60+ . catch ( function ( error ) {
61+ callback ( self . getSystemTheme ( ) ) ;
62+ } ) ;
63+ } ,
64+
65+ saveServerThemePreference : function ( theme ) {
66+ if ( ! this . isAuthenticated ) {
67+ return ;
68+ }
69+
70+ var userId = this . getCurrentUserId ( ) ;
71+ if ( ! userId ) {
72+ return ;
73+ }
74+
75+ fetch ( '/accounts/' + userId + '/set_theme_preference' , {
76+ method : 'POST' ,
77+ credentials : 'same-origin' ,
78+ headers : {
79+ 'Content-Type' : 'application/json' ,
80+ 'X-CSRF-Token' : this . getCsrfToken ( )
81+ } ,
82+ body : JSON . stringify ( { theme : theme } )
83+ } )
84+ . then ( function ( response ) {
85+ return response . json ( ) ;
86+ } )
87+ . catch ( function ( error ) {
88+ // Silent fail - cookie already set
89+ } ) ;
90+ } ,
91+
92+ getCsrfToken : function ( ) {
93+ var token = document . querySelector ( 'meta[name="csrf-token"]' ) ;
94+ return token ? token . getAttribute ( 'content' ) : '' ;
95+ } ,
96+
97+ getCookie : function ( name ) {
98+ var nameEQ = name + '=' ;
99+ var cookies = document . cookie . split ( ';' ) ;
100+ for ( var i = 0 ; i < cookies . length ; i ++ ) {
101+ var cookie = cookies [ i ] . trim ( ) ;
102+ if ( cookie . indexOf ( nameEQ ) === 0 ) {
103+ return cookie . substring ( nameEQ . length ) ;
104+ }
105+ }
106+ return null ;
107+ } ,
108+
109+ setCookie : function ( name , value , days ) {
110+ var expires = '' ;
111+ if ( days ) {
112+ var date = new Date ( ) ;
113+ date . setTime ( date . getTime ( ) + ( days * 24 * 60 * 60 * 1000 ) ) ;
114+ expires = '; expires=' + date . toUTCString ( ) ;
115+ }
116+ document . cookie = name + '=' + value + expires + '; path=/; SameSite=Lax' ;
117+ } ,
118+
119+ getSystemTheme : function ( ) {
120+ if ( window . matchMedia && window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ) {
121+ return 'dark' ;
122+ }
123+ return 'light' ;
9124 } ,
10125
11126 getSavedTheme : function ( ) {
12- try {
13- return localStorage . getItem ( 'theme' ) || 'light' ;
14- } catch ( e ) {
15- return 'light' ;
127+ var cookieTheme = this . getCookie ( this . COOKIE_NAME ) ;
128+ if ( cookieTheme && ( cookieTheme === 'light' || cookieTheme === 'dark' ) ) {
129+ return cookieTheme ;
16130 }
131+ return this . getSystemTheme ( ) ;
17132 } ,
18133
19134 applyTheme : function ( theme ) {
@@ -31,11 +146,7 @@ var ThemeToggle = {
31146 if ( sunIcon ) sunIcon . classList . add ( 'hidden' ) ;
32147 }
33148
34- try {
35- localStorage . setItem ( 'theme' , theme ) ;
36- } catch ( e ) {
37- console . log ( 'Could not save theme preference' ) ;
38- }
149+ this . setCookie ( this . COOKIE_NAME , theme , this . COOKIE_DAYS ) ;
39150
40151 if ( typeof Charts !== 'undefined' ) {
41152 Charts . updateWatermarks ( theme === 'dark' ) ;
@@ -46,24 +157,21 @@ var ThemeToggle = {
46157 var currentTheme = this . getSavedTheme ( ) ;
47158 var newTheme = currentTheme === 'light' ? 'dark' : 'light' ;
48159 this . applyTheme ( newTheme ) ;
160+ if ( this . isAuthenticated ) {
161+ this . saveServerThemePreference ( newTheme ) ;
162+ }
49163 } ,
50164
51165 bindEvents : function ( ) {
52166 var self = this ;
53167 var themeToggleBtn = document . getElementById ( 'theme-toggle' ) ;
54168
55- console . log ( 'ThemeToggle: Theme toggle button found?' , ! ! themeToggleBtn ) ;
56-
57169 if ( themeToggleBtn ) {
58170 themeToggleBtn . onclick = function ( e ) {
59171 e . preventDefault ( ) ;
60- console . log ( 'ThemeToggle: Toggle clicked!' ) ;
61172 self . toggleTheme ( ) ;
62173 return false ;
63174 } ;
64- console . log ( 'ThemeToggle: Click handler attached' ) ;
65- } else {
66- console . log ( 'ThemeToggle: WARNING - Theme toggle button not found!' ) ;
67175 }
68176 }
69177} ;
0 commit comments