@@ -139,7 +139,7 @@ async function api(path, options = {}) {
139139 state . user = null ;
140140 localStorage . removeItem ( 'zh_token' ) ;
141141 localStorage . removeItem ( 'zh_user' ) ;
142- renderLoginPage ( ) ;
142+ navigateTo ( 'login' ) ;
143143 throw new Error ( 'Session expired. Please sign in again.' ) ;
144144 }
145145 if ( ! res . ok ) throw new Error ( data . error || 'Request failed' ) ;
@@ -245,7 +245,7 @@ function renderLoginPage() {
245245
246246 </ form >
247247 < div class ="auth-footer ">
248- Don't have an account? < a href ="# " id ="go-register "> Create one</ a >
248+ Don't have an account? < a href ="/signup " id ="go-register "> Create one</ a >
249249 </ div >
250250 </ div >
251251 </ div >
@@ -254,7 +254,7 @@ function renderLoginPage() {
254254 $ ( '#login-form' ) . addEventListener ( 'submit' , handleLogin ) ;
255255 $ ( '#go-register' ) . addEventListener ( 'click' , ( e ) => {
256256 e . preventDefault ( ) ;
257- renderRegisterPage ( ) ;
257+ navigateTo ( 'signup' ) ;
258258 } ) ;
259259}
260260
@@ -298,7 +298,7 @@ function renderRegisterPage() {
298298
299299 </ form >
300300 < div class ="auth-footer ">
301- Already have an account? < a href ="# " id ="go-login "> Sign in</ a >
301+ Already have an account? < a href ="/login " id ="go-login "> Sign in</ a >
302302 </ div >
303303 </ div >
304304 </ div >
@@ -307,7 +307,7 @@ function renderRegisterPage() {
307307 $ ( '#register-form' ) . addEventListener ( 'submit' , handleRegister ) ;
308308 $ ( '#go-login' ) . addEventListener ( 'click' , ( e ) => {
309309 e . preventDefault ( ) ;
310- renderLoginPage ( ) ;
310+ navigateTo ( 'login' ) ;
311311 } ) ;
312312}
313313
@@ -332,6 +332,7 @@ async function handleLogin(e) {
332332 state . user = data . user ;
333333 localStorage . setItem ( 'zh_token' , data . token ) ;
334334 localStorage . setItem ( 'zh_user' , JSON . stringify ( data . user ) ) ;
335+ history . replaceState ( { page : 'overview' } , '' , '/' ) ;
335336 renderDashboard ( ) ;
336337 } catch ( err ) {
337338 showError ( e . target , err . message ) ;
@@ -371,6 +372,7 @@ async function handleRegister(e) {
371372 state . user = data . user ;
372373 localStorage . setItem ( 'zh_token' , data . token ) ;
373374 localStorage . setItem ( 'zh_user' , JSON . stringify ( data . user ) ) ;
375+ history . replaceState ( { page : 'overview' } , '' , '/' ) ;
374376 renderDashboard ( ) ;
375377 } catch ( err ) {
376378 showError ( e . target , err . message ) ;
@@ -471,7 +473,7 @@ async function renderDashboard() {
471473 < nav class ="sidebar-nav ">
472474 < div class ="nav-indicator " id ="nav-indicator "> </ div >
473475 < div class ="nav-section-label "> Main</ div >
474- < a class ="nav-item active " data-page ="overview " href ="/overview ">
476+ < a class ="nav-item active " data-page ="overview " href ="/ ">
475477 < svg viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 "> < rect x ="3 " y ="3 " width ="7 " height ="7 " rx ="1 "/> < rect x ="14 " y ="3 " width ="7 " height ="7 " rx ="1 "/> < rect x ="3 " y ="14 " width ="7 " height ="7 " rx ="1 "/> < rect x ="14 " y ="14 " width ="7 " height ="7 " rx ="1 "/> </ svg >
476478 Overview
477479 </ a >
@@ -551,7 +553,7 @@ async function renderDashboard() {
551553 state . user = null ;
552554 localStorage . removeItem ( 'zh_token' ) ;
553555 localStorage . removeItem ( 'zh_user' ) ;
554- renderLoginPage ( ) ;
556+ navigateTo ( 'login' ) ;
555557 } ) ;
556558
557559 $ ( '#sidebar-user-info' ) . addEventListener ( 'click' , ( e ) => {
@@ -629,17 +631,48 @@ function initSidebarTooltip() {
629631}
630632
631633function navigateTo ( page ) {
632- document . querySelectorAll ( '.page' ) . forEach ( p => p . classList . remove ( 'active' ) ) ;
633- document . querySelectorAll ( '.nav-item' ) . forEach ( n => n . classList . remove ( 'active' ) ) ;
634-
635634 const parts = page . split ( '/' ) ;
636- const basePage = parts [ 0 ] ;
635+ let basePage = parts [ 0 ] || 'overview' ;
637636 const param = parts [ 1 ] ;
638637
638+ // Auth pages - redirect to / if already logged in
639+ if ( ( basePage === 'login' || basePage === 'signup' ) && state . token ) {
640+ basePage = 'overview' ;
641+ }
642+
643+ // Handle auth pages (no dashboard needed)
644+ if ( basePage === 'login' ) {
645+ renderLoginPage ( ) ;
646+ history . pushState ( { page : 'login' } , '' , '/login' ) ;
647+ return ;
648+ }
649+ if ( basePage === 'signup' ) {
650+ renderRegisterPage ( ) ;
651+ history . pushState ( { page : 'signup' } , '' , '/signup' ) ;
652+ return ;
653+ }
654+
655+ // Auth guard: require valid token for all other pages
656+ if ( ! state . token ) {
657+ renderLoginPage ( ) ;
658+ history . pushState ( { page : 'login' } , '' , '/login' ) ;
659+ return ;
660+ }
661+
662+ // Ensure dashboard layout exists
663+ if ( ! document . querySelector ( '.dashboard-layout' ) ) {
664+ renderDashboard ( ) ;
665+ return ;
666+ }
667+
668+ document . querySelectorAll ( '.page' ) . forEach ( p => p . classList . remove ( 'active' ) ) ;
669+ document . querySelectorAll ( '.nav-item' ) . forEach ( n => n . classList . remove ( 'active' ) ) ;
670+
639671 state . currentPage = basePage ;
640672 state . serverId = param ? parseInt ( param ) : null ;
641673 state . serverDetailTab = 'info' ;
642- history . pushState ( { page : basePage , serverId : state . serverId } , '' , `/${ page } ` ) ;
674+ const url = basePage === 'overview' && ! param ? '/' : `/${ page } ` ;
675+ history . pushState ( { page : basePage , serverId : state . serverId } , '' , url ) ;
643676
644677 if ( basePage === 'server' && state . serverId ) {
645678 const targetPage = $ ( '#page-server-detail' ) ;
@@ -687,9 +720,18 @@ function updateNavIndicator() {
687720window . addEventListener ( 'popstate' , ( ) => {
688721 const path = window . location . pathname ;
689722 const parts = path . replace ( / ^ \/ / , '' ) . split ( '/' ) ;
690- const basePage = parts [ 0 ] || 'overview' ;
723+ let basePage = parts [ 0 ] || 'overview' ;
691724 const param = parts [ 1 ] ;
692725
726+ // Auth pages - redirect to / if already logged in
727+ if ( ( basePage === 'login' || basePage === 'signup' ) && state . token ) {
728+ basePage = 'overview' ;
729+ }
730+
731+ if ( basePage === 'login' ) { renderLoginPage ( ) ; return ; }
732+ if ( basePage === 'signup' ) { renderRegisterPage ( ) ; return ; }
733+ if ( ! state . token ) { renderLoginPage ( ) ; return ; }
734+
693735 document . querySelectorAll ( '.page' ) . forEach ( p => p . classList . remove ( 'active' ) ) ;
694736 document . querySelectorAll ( '.nav-item' ) . forEach ( n => n . classList . remove ( 'active' ) ) ;
695737
@@ -1413,7 +1455,7 @@ function renderAccount() {
14131455 state . user = null ;
14141456 localStorage . removeItem ( 'zh_token' ) ;
14151457 localStorage . removeItem ( 'zh_user' ) ;
1416- renderLoginPage ( ) ;
1458+ navigateTo ( 'login' ) ;
14171459 } ) ;
14181460}
14191461
@@ -1698,7 +1740,7 @@ async function handleConfirmDeleteAccount() {
16981740 state . user = null ;
16991741 localStorage . removeItem ( 'zh_token' ) ;
17001742 localStorage . removeItem ( 'zh_user' ) ;
1701- setTimeout ( ( ) => renderLoginPage ( ) , 1500 ) ;
1743+ setTimeout ( ( ) => navigateTo ( 'login' ) , 1500 ) ;
17021744 } catch ( err ) {
17031745 showToast ( err . message , 'error' ) ;
17041746 btn . disabled = false ;
@@ -2228,19 +2270,36 @@ async function handleExportData() {
22282270
22292271// ===== INIT =====
22302272function init ( ) {
2273+ const path = window . location . pathname ;
2274+ const basePage = path . replace ( / ^ \/ / , '' ) . split ( '/' ) [ 0 ] || '' ;
22312275 const token = localStorage . getItem ( 'zh_token' ) ;
2276+
22322277 if ( token ) {
22332278 state . token = token ;
22342279 try {
22352280 const user = JSON . parse ( localStorage . getItem ( 'zh_user' ) ) ;
22362281 if ( user ) state . user = user ;
22372282 } catch { }
2283+ }
2284+
2285+ if ( basePage === 'login' || basePage === 'signup' ) {
2286+ if ( state . token ) {
2287+ history . replaceState ( { page : 'overview' } , '' , '/' ) ;
2288+ renderDashboard ( ) ;
2289+ } else if ( basePage === 'login' ) {
2290+ renderLoginPage ( ) ;
2291+ } else {
2292+ renderRegisterPage ( ) ;
2293+ }
2294+ } else if ( state . token ) {
22382295 api ( '/servers/overview' ) . then ( ( ) => renderDashboard ( ) ) . catch ( ( ) => {
22392296 renderDashboard ( ) ;
22402297 } ) ;
22412298 } else {
22422299 renderLoginPage ( ) ;
2300+ history . replaceState ( { page : 'login' } , '' , '/login' ) ;
22432301 }
2302+
22442303 renderCookieBanner ( ) ;
22452304}
22462305
0 commit comments