@@ -4,18 +4,15 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
44
55type Phase = { href : string ; label : string } ;
66
7- /** Same order as the admin hub: wheel → pandora → three quiz boards. */
87const PHASES : Phase [ ] = [
9- { href : "/" , label : "Колесо — ведущий" } ,
10- { href : "/adepts" , label : "Колесо — ведущий Adepts" } ,
11- { href : "/watch" , label : "Колесо — зрители" } ,
12- { href : "/game" , label : "Пандора — игроки" } ,
13- { href : "/spectate" , label : "Пандора — ведущий" } ,
148 { href : "/adepts-game/" , label : "Квиз-доска 1" } ,
159 { href : "/adepts-game-2/" , label : "Квиз-доска 2" } ,
1610 { href : "/adepts-game-3/" , label : "Квиз-доска 3" } ,
1711] ;
1812
13+ /** Routes that render their own inline phase nav inside a header. */
14+ const HEADER_NAV_ROUTES = [ "/adepts-game" , "/adepts-game-2" , "/adepts-game-3" ] ;
15+
1916function stripBase ( pathname : string , base : string ) : string {
2017 const b = base . replace ( / \/ $ / , "" ) ;
2118 if ( ! b ) return pathname || "/" ;
@@ -41,17 +38,23 @@ function phaseIndexForPath(relPath: string): number {
4138 return - 1 ;
4239}
4340
44- export function GamePhaseArrows ( ) {
41+ function usePhaseIndex ( ) {
4542 const [ location ] = useLocation ( ) ;
4643 const base = import . meta. env . BASE_URL . replace ( / \/ $ / , "" ) ;
4744
48- const index = useMemo ( ( ) => {
45+ return useMemo ( ( ) => {
4946 const fullPath = typeof window !== "undefined" ? window . location . pathname : location ;
5047 const rel = stripBase ( fullPath , base ) ;
51- return phaseIndexForPath ( rel ) ;
48+ return { index : phaseIndexForPath ( rel ) , rel } ;
5249 } , [ location , base ] ) ;
50+ }
5351
54- if ( index < 0 ) return null ;
52+ /** Floating pill fixed at bottom-center. Rendered globally for pages without a header. */
53+ export function GamePhaseArrows ( ) {
54+ const { index, rel } = usePhaseIndex ( ) ;
55+
56+ const isHeaderRoute = HEADER_NAV_ROUTES . some ( ( r ) => normalize ( rel ) . startsWith ( normalize ( r ) ) ) ;
57+ if ( index < 0 || isHeaderRoute ) return null ;
5558
5659 const prev = index > 0 ? PHASES [ index - 1 ] : null ;
5760 const next = index < PHASES . length - 1 ? PHASES [ index + 1 ] : null ;
@@ -98,3 +101,55 @@ export function GamePhaseArrows() {
98101 </ nav >
99102 ) ;
100103}
104+
105+ /** Compact inline nav for use inside a page header.
106+ * Uses plain <a> tags so nested wouter routers don't mangle the absolute hrefs. */
107+ export function GamePhaseNav ( ) {
108+ const { index } = usePhaseIndex ( ) ;
109+ const base = import . meta. env . BASE_URL . replace ( / \/ $ / , "" ) ;
110+
111+ if ( index < 0 ) return null ;
112+
113+ const prev = index > 0 ? PHASES [ index - 1 ] : null ;
114+ const next = index < PHASES . length - 1 ? PHASES [ index + 1 ] : null ;
115+
116+ const toHref = ( phase : Phase ) => base + phase . href ;
117+
118+ return (
119+ < nav className = "flex items-center gap-0.5" aria-label = "Переход между фазами игры" >
120+ { prev ? (
121+ < a
122+ href = { toHref ( prev ) }
123+ className = "flex h-7 w-7 items-center justify-center rounded-full text-white/70 transition hover:bg-white/10 hover:text-amber-300"
124+ title = { `Назад: ${ prev . label } ` }
125+ aria-label = { `Предыдущая фаза: ${ prev . label } ` }
126+ >
127+ < ChevronLeft className = "h-4 w-4" strokeWidth = { 2.5 } />
128+ </ a >
129+ ) : (
130+ < span className = "flex h-7 w-7 items-center justify-center text-white/20" aria-hidden >
131+ < ChevronLeft className = "h-4 w-4" />
132+ </ span >
133+ ) }
134+
135+ < span className = "px-1 text-[10px] font-mono text-white/50 tabular-nums" >
136+ { index + 1 } /{ PHASES . length }
137+ </ span >
138+
139+ { next ? (
140+ < a
141+ href = { toHref ( next ) }
142+ className = "flex h-7 w-7 items-center justify-center rounded-full text-white/70 transition hover:bg-white/10 hover:text-amber-300"
143+ title = { `Вперёд: ${ next . label } ` }
144+ aria-label = { `Следующая фаза: ${ next . label } ` }
145+ >
146+ < ChevronRight className = "h-4 w-4" strokeWidth = { 2.5 } />
147+ </ a >
148+ ) : (
149+ < span className = "flex h-7 w-7 items-center justify-center text-white/20" aria-hidden >
150+ < ChevronRight className = "h-4 w-4" />
151+ </ span >
152+ ) }
153+ </ nav >
154+ ) ;
155+ }
0 commit comments