11"use client" ;
22
3- import { useState , useEffect , useMemo } from "react" ;
3+ import { Suspense , useState , useEffect , useMemo } from "react" ;
44import { Search , X , Target , Crosshair , Flame , Calendar } from "lucide-react" ;
55import { motion , AnimatePresence } from "framer-motion" ;
66import Link from "next/link" ;
7+ import { useSearchParams , useRouter } from "next/navigation" ;
78import {
89 getAreas , getVaultStats , getAreaStyle , getAreaForTopic , searchTopics ,
910 type Topic ,
@@ -17,13 +18,44 @@ import { isDailyCompleted } from "@/lib/daily";
1718import manifest from "@/data/vault-manifest.json" ;
1819import { ECOSYSTEM_BASE } from "@/lib/env" ;
1920
20- export default function HomePage ( ) {
21+ function formatTrackLabel ( t : string ) {
22+ return t === "tinyml" ? "TinyML" : t . charAt ( 0 ) . toUpperCase ( ) + t . slice ( 1 ) ;
23+ }
24+
25+ export default function HomePageWrapper ( ) {
26+ return (
27+ < Suspense fallback = {
28+ < div className = "flex-1 flex items-center justify-center" >
29+ < Search className = "w-6 h-6 text-textTertiary animate-pulse" />
30+ </ div >
31+ } >
32+ < HomePage />
33+ </ Suspense >
34+ ) ;
35+ }
36+
37+ function HomePage ( ) {
38+ const searchParams = useSearchParams ( ) ;
39+ const router = useRouter ( ) ;
2140 const [ mounted , setMounted ] = useState ( false ) ;
2241 const [ query , setQuery ] = useState ( "" ) ;
2342 const [ selectedTopic , setSelectedTopic ] = useState < Topic | null > ( null ) ;
2443 const [ selectedAreas , setSelectedAreas ] = useState < Set < string > > ( new Set ( ) ) ;
2544 const [ showAllAreas , setShowAllAreas ] = useState ( false ) ;
26- const [ selectedTrack , setSelectedTrack ] = useState < string | null > ( null ) ;
45+
46+ // Initialize track from URL param, sync changes back to URL
47+ const validTracks = getTracks ( ) ;
48+ const initialTrack = searchParams . get ( "track" ) ;
49+ const [ selectedTrack , setSelectedTrackState ] = useState < string | null > (
50+ initialTrack && validTracks . includes ( initialTrack ) ? initialTrack : null
51+ ) ;
52+ const setSelectedTrack = ( track : string | null ) => {
53+ setSelectedTrackState ( track ) ;
54+ const params = new URLSearchParams ( searchParams . toString ( ) ) ;
55+ if ( track ) { params . set ( "track" , track ) ; } else { params . delete ( "track" ) ; }
56+ const qs = params . toString ( ) ;
57+ router . replace ( qs ? `/?${ qs } ` : "/" , { scroll : false } ) ;
58+ } ;
2759 const [ isReturning , setIsReturning ] = useState ( false ) ;
2860 const [ streakCount , setStreakCount ] = useState ( 0 ) ;
2961 const [ attemptCount , setAttemptCount ] = useState ( 0 ) ;
@@ -154,7 +186,15 @@ export default function HomePage() {
154186 </ h1 >
155187 < p className = "text-[13px] text-textSecondary mb-3" >
156188 Free, open-source interview prep for ML systems engineers.{ " " }
157- { stats . totalQuestions . toLocaleString ( ) } questions across compute, memory, latency, and more.
189+ { selectedTrack ? (
190+ < >
191+ < span className = "font-semibold" > { formatTrackLabel ( selectedTrack ) } </ span > track:{ " " }
192+ { filteredAreas . reduce ( ( s , a ) => s + a . questionCount , 0 ) . toLocaleString ( ) } of{ " " }
193+ { stats . totalQuestions . toLocaleString ( ) } questions.
194+ </ >
195+ ) : (
196+ < > { stats . totalQuestions . toLocaleString ( ) } questions across compute, memory, latency, and more.</ >
197+ ) }
158198 </ p >
159199
160200 { /* Welcome guide */ }
@@ -384,6 +424,7 @@ export default function HomePage() {
384424 >
385425 < TopicDetail topic = { selectedTopic }
386426 areaName = { selectedArea ?. name || "" } style = { selectedStyle }
427+ selectedTrack = { selectedTrack }
387428 onClose = { ( ) => setSelectedTopic ( null ) } />
388429 </ motion . div >
389430 ) }
@@ -416,6 +457,7 @@ export default function HomePage() {
416457 </ div >
417458 < TopicDetail topic = { selectedTopic }
418459 areaName = { selectedArea ?. name || "" } style = { selectedStyle }
460+ selectedTrack = { selectedTrack }
419461 onClose = { ( ) => setSelectedTopic ( null ) } />
420462 </ motion . div >
421463 </ >
0 commit comments