@@ -86,6 +86,10 @@ const Participant = () => {
8686 const [ isBonusMode , setIsBonusMode ] = useState ( false ) ;
8787 const [ completedBonus , setCompletedBonus ] = useState ( 0 ) ;
8888
89+ const [ eventNotStarted , setEventNotStarted ] = useState ( false ) ;
90+ const [ eventStartTime , setEventStartTime ] = useState ( null ) ;
91+ const [ timeLeft , setTimeLeft ] = useState ( { obj : null , str : '' } ) ;
92+
8993 useEffect ( ( ) => { fetchCurrentQuestion ( false ) ; } , [ ] ) ;
9094
9195 const fetchCurrentQuestion = async ( isBonus = false ) => {
@@ -105,6 +109,11 @@ const Participant = () => {
105109 } ) ;
106110 if ( response . question_number ) setQuestionNumber ( prev => Math . max ( prev , response . question_number ) ) ;
107111 setCompletedBonus ( response . completed_bonus || 0 ) ;
112+ setEventNotStarted ( false ) ;
113+ } else if ( response . not_started ) {
114+ setEventNotStarted ( true ) ;
115+ setEventStartTime ( response . event_start ) ;
116+ setCurrentQuestion ( null ) ;
108117 } else if ( response . completed ) {
109118 if ( isBonus ) {
110119 setError ( 'No more bonus questions available on this path!' ) ;
@@ -126,6 +135,41 @@ const Participant = () => {
126135 }
127136 } ;
128137
138+ useEffect ( ( ) => {
139+ let timer ;
140+ if ( eventNotStarted && eventStartTime ) {
141+ const targetDate = new Date ( eventStartTime ) ;
142+ const updateTimer = ( ) => {
143+ const now = new Date ( ) ;
144+ const diff = targetDate - now ;
145+ if ( diff <= 0 ) {
146+ clearInterval ( timer ) ;
147+ setEventNotStarted ( false ) ;
148+ fetchCurrentQuestion ( false ) ; // Fetch questions now that event started
149+ } else {
150+ const d = Math . floor ( diff / ( 1000 * 60 * 60 * 24 ) ) ;
151+ const h = Math . floor ( ( diff % ( 1000 * 60 * 60 * 24 ) ) / ( 1000 * 60 * 60 ) ) ;
152+ const m = Math . floor ( ( diff % ( 1000 * 60 * 60 ) ) / ( 1000 * 60 ) ) ;
153+ const s = Math . floor ( ( diff % ( 1000 * 60 ) ) / 1000 ) ;
154+
155+ let parts = [ ] ;
156+ if ( d > 0 ) parts . push ( `${ d } d` ) ;
157+ if ( d > 0 || h > 0 ) parts . push ( `${ h } h` ) ;
158+ parts . push ( `${ m } m` ) ;
159+ parts . push ( `${ s } s` ) ;
160+
161+ setTimeLeft ( {
162+ obj : { d, h, m, s } ,
163+ str : parts . join ( ' ' )
164+ } ) ;
165+ }
166+ } ;
167+ updateTimer ( ) ;
168+ timer = setInterval ( updateTimer , 1000 ) ;
169+ }
170+ return ( ) => clearInterval ( timer ) ;
171+ } , [ eventNotStarted , eventStartTime ] ) ;
172+
129173 // Compress image using canvas — returns a File under targetSize
130174 const compressImage = ( file , maxWidth = 1200 , quality = 0.7 , targetSizeMB = 2 ) => {
131175 return new Promise ( ( resolve ) => {
@@ -277,6 +321,42 @@ const Participant = () => {
277321 /* ─── Completion state ──── */
278322 if ( currentQuestion ?. completed ) return < CompletionScreen /> ;
279323
324+ /* ─── Event Not Started state ──── */
325+ if ( eventNotStarted ) {
326+ return (
327+ < div className = "flex-col-center" style = { { flex : 1 , position : 'relative' , padding : '2rem' } } >
328+ < DottedPath />
329+ < motion . div
330+ initial = { { scale : 0.9 , opacity : 0 } }
331+ animate = { { scale : 1 , opacity : 1 } }
332+ className = "adventure-card"
333+ style = { { textAlign : 'center' , maxWidth : 400 , border : '3px solid var(--color-green)' } }
334+ >
335+ < span style = { { fontSize : '3rem' , display : 'block' , marginBottom : '0.8rem' , animation : 'spin 10s linear infinite' } } > ⏳</ span >
336+ < h2 style = { { fontSize : '1.6rem' , color : 'var(--color-green)' , marginBottom : '0.5rem' , fontFamily : 'var(--font-heading)' } } >
337+ THE VOYAGE BEGINS SOON
338+ </ h2 >
339+ < p style = { { color : 'var(--color-brown)' , fontWeight : 600 , fontSize : '1rem' , marginBottom : '1.5rem' , fontFamily : 'var(--font-body)' } } >
340+ Hold tight, explorer. Your treasure map is still being charted.
341+ </ p >
342+
343+ < div style = { {
344+ background : 'var(--color-bg-primary)' ,
345+ padding : '1.2rem' ,
346+ borderRadius : '12px' ,
347+ border : '2px dashed var(--color-green-light)' ,
348+ display : 'inline-block'
349+ } } >
350+ < div style = { { fontSize : '0.8rem' , color : 'var(--color-green)' , letterSpacing : 2 , marginBottom : '0.5rem' , fontWeight : 800 } } > STARTS IN</ div >
351+ < div style = { { fontSize : '2rem' , fontFamily : 'var(--font-heading)' , color : 'var(--color-red)' , letterSpacing : '1px' } } >
352+ { timeLeft . str || "Loading..." }
353+ </ div >
354+ </ div >
355+ </ motion . div >
356+ </ div >
357+ ) ;
358+ }
359+
280360 /* ─── No question found ──── */
281361 if ( ! currentQuestion ) {
282362 return (
0 commit comments