11"use client" ;
22
3- import { useMemo , useState } from "react" ;
3+ import { Suspense , useEffect , useEffectEvent , useMemo , useRef , useState } from "react" ;
4+ import { useRouter , useSearchParams } from "next/navigation" ;
45import { CompareForm } from "../components/compare-form" ;
56import { ResultDashboard } from "../components/result-dashboard" ;
67import { DashboardSkeleton } from "../components/skeletons" ;
@@ -16,14 +17,24 @@ type ApiResponse = {
1617 error ?: string ;
1718} ;
1819
19- export default function HomePage ( ) {
20+ function HomePageInner ( ) {
2021 const { t } = useTranslation ( ) ;
22+ const router = useRouter ( ) ;
23+ const searchParams = useSearchParams ( ) ;
24+ const initialUsernames = searchParams . getAll ( "username" ) ;
25+ const initialUsername1 = initialUsernames [ 0 ] ?? "" ;
26+ const initialUsername2 = initialUsernames [ 1 ] ?? "" ;
2127 const [ loading , setLoading ] = useState ( false ) ;
2228 const [ error , setError ] = useState < string | null > ( null ) ;
29+ const [ username1 , setUsername1 ] = useState ( initialUsername1 ) ;
30+ const [ username2 , setUsername2 ] = useState ( initialUsername2 ) ;
2331 const [ data , setData ] = useState < {
2432 user1 : UserResult ;
2533 user2 : UserResult ;
2634 } | null > ( null ) ;
35+ // Track the URL pair we last fetched against so back/forward navigation
36+ // can resync the form and results without re-fetching identical pairs.
37+ const lastFetchedPairRef = useRef < [ string , string ] | null > ( null ) ;
2738
2839 const localizeErrorMessage = ( message ?: string ) => {
2940 switch ( message ) {
@@ -43,6 +54,11 @@ export default function HomePage() {
4354 } ;
4455
4556 const handleCompare = async ( u1 : string , u2 : string ) => {
57+ lastFetchedPairRef . current = [ u1 , u2 ] ;
58+ router . push (
59+ `/?username=${ encodeURIComponent ( u1 ) } &username=${ encodeURIComponent ( u2 ) } ` ,
60+ { scroll : false }
61+ ) ;
4662 setLoading ( true ) ;
4763 setError ( null ) ;
4864 setData ( null ) ;
@@ -79,14 +95,56 @@ export default function HomePage() {
7995 }
8096 } ;
8197
98+ // Resync form + results to whatever the URL says — handles initial mount
99+ // AND back/forward navigation. We fetch only when the URL pair differs from
100+ // the last pair we fetched, so no infinite loop with the router.push above.
101+ const syncToUrl = useEffectEvent ( ( u1 : string , u2 : string ) => {
102+ setUsername1 ( u1 ) ;
103+ setUsername2 ( u2 ) ;
104+
105+ if ( ! u1 || ! u2 ) {
106+ // Empty params: clear results so the empty state matches the URL.
107+ lastFetchedPairRef . current = null ;
108+ setData ( null ) ;
109+ setError ( null ) ;
110+ return ;
111+ }
112+
113+ const last = lastFetchedPairRef . current ;
114+ if ( last && last [ 0 ] === u1 && last [ 1 ] === u2 ) {
115+ // URL already reflects the most recent fetch; nothing to do.
116+ return ;
117+ }
118+
119+ void handleCompare ( u1 , u2 ) ;
120+ } ) ;
121+
122+ useEffect ( ( ) => {
123+ const params = searchParams . getAll ( "username" ) ;
124+ syncToUrl ( params [ 0 ] ?? "" , params [ 1 ] ?? "" ) ;
125+ } , [ searchParams ] ) ;
126+
82127 const skeleton = useMemo ( ( ) => < DashboardSkeleton /> , [ ] ) ;
83128
84129 const reset = ( ) => {
85130 setData ( null ) ;
86131 setError ( null ) ;
132+ setUsername1 ( "" ) ;
133+ setUsername2 ( "" ) ;
134+ router . push ( "/" , { scroll : false } ) ;
87135 } ;
88136
89137 const swapUsers = ( ) => {
138+ const nextUsername1 = username2 ;
139+ const nextUsername2 = username1 ;
140+
141+ setUsername1 ( nextUsername1 ) ;
142+ setUsername2 ( nextUsername2 ) ;
143+ router . push (
144+ `/?username=${ encodeURIComponent ( nextUsername1 ) } &username=${ encodeURIComponent ( nextUsername2 ) } ` ,
145+ { scroll : false }
146+ ) ;
147+
90148 if ( ! data ) return ;
91149 setData ( ( d ) => ( { user1 : d ! . user2 , user2 : d ! . user1 } ) ) ;
92150 } ;
@@ -97,6 +155,10 @@ export default function HomePage() {
97155
98156 < div className = "w-full flex-1 max-w-6xl mx-auto px-4 py-10 space-y-6" >
99157 < CompareForm
158+ username1 = { username1 }
159+ username2 = { username2 }
160+ setUsername1 = { setUsername1 }
161+ setUsername2 = { setUsername2 }
100162 onSubmit = { handleCompare }
101163 loading = { loading }
102164 reset = { reset }
@@ -126,3 +188,11 @@ export default function HomePage() {
126188 </ main >
127189 ) ;
128190}
191+
192+ export default function HomePage ( ) {
193+ return (
194+ < Suspense fallback = { < DashboardSkeleton /> } >
195+ < HomePageInner />
196+ </ Suspense >
197+ ) ;
198+ }
0 commit comments