22
33import { ExternalLink } from 'lucide-react'
44import { useTranslations } from 'next-intl'
5- import { Fragment , useEffect , useState } from 'react'
5+ import { Fragment , useEffect , useRef } from 'react'
6+ import { useModelComparison } from '@/components/controls/useModelComparison'
67import type { Locale } from '@/i18n/config'
78import { Link , useRouter } from '@/i18n/navigation'
89import { providersData } from '@/lib/generated'
10+ import { buildModelComparisonPath } from '@/lib/model-comparison'
911import type {
1012 ManifestBenchmarks ,
1113 ManifestModel ,
@@ -180,10 +182,17 @@ export default function ComparePageClient({
180182 const router = useRouter ( )
181183 const tPage = useTranslations ( 'pages.modelCompare' )
182184 const tShared = useTranslations ( 'shared' )
183- const [ selectedModel1 , setSelectedModel1 ] = useState < string > ( initialModels [ 0 ] ?. id ?? '' )
184- const [ selectedModel2 , setSelectedModel2 ] = useState < string > ( initialModels [ 1 ] ?. id ?? '' )
185- const [ prevModel1 , setPrevModel1 ] = useState < string > ( initialModels [ 0 ] ?. id ?? '' )
186- const [ prevModel2 , setPrevModel2 ] = useState < string > ( initialModels [ 1 ] ?. id ?? '' )
185+ const initialModelIds = initialModels . map ( model => model . id )
186+ const { selectedIds, isHydrated, setSelection } = useModelComparison ( initialModelIds )
187+ const selectedModel1 = selectedIds [ 0 ] ?? ''
188+ const selectedModel2 = selectedIds [ 1 ] ?? ''
189+ const lastComparisonPath = useRef ( buildModelComparisonPath ( initialModelIds ) )
190+
191+ const updateModelSlot = ( slotIndex : number , value : string ) => {
192+ const nextSelection = [ selectedModel1 , selectedModel2 ]
193+ nextSelection [ slotIndex ] = value
194+ setSelection ( nextSelection . filter ( Boolean ) )
195+ }
187196
188197 const findProviderId = ( vendor : string ) : string | null => {
189198 const normalizedVendor = vendor . toLocaleLowerCase ( )
@@ -471,17 +480,14 @@ export default function ComparePageClient({
471480 )
472481 }
473482
474- // Update URL when both models are selected and at least one has changed
483+ // Keep the shareable URL aligned with the persisted selection.
475484 useEffect ( ( ) => {
476- if ( selectedModel1 && selectedModel2 && selectedModel1 !== selectedModel2 ) {
477- if ( selectedModel1 !== prevModel1 || selectedModel2 !== prevModel2 ) {
478- const url = `/models/compare/${ selectedModel1 } -vs-${ selectedModel2 } `
479- router . push ( url )
480- setPrevModel1 ( selectedModel1 )
481- setPrevModel2 ( selectedModel2 )
482- }
483- }
484- } , [ selectedModel1 , selectedModel2 , prevModel1 , prevModel2 , router ] )
485+ if ( ! isHydrated ) return
486+ const nextPath = buildModelComparisonPath ( selectedIds )
487+ if ( nextPath === lastComparisonPath . current ) return
488+ lastComparisonPath . current = nextPath
489+ router . replace ( nextPath )
490+ } , [ isHydrated , router , selectedIds ] )
485491
486492 const model1 = allModels . find ( m => m . id === selectedModel1 )
487493 const model2 = allModels . find ( m => m . id === selectedModel2 )
@@ -498,7 +504,7 @@ export default function ComparePageClient({
498504 < div className = "flex flex-col gap-2 items-center" >
499505 < ModelSelect
500506 value = { selectedModel1 }
501- onChange = { setSelectedModel1 }
507+ onChange = { value => updateModelSlot ( 0 , value ) }
502508 availableModels = { getAvailableModelsForSlot ( 0 ) }
503509 />
504510 </ div >
@@ -507,7 +513,7 @@ export default function ComparePageClient({
507513 < div className = "flex flex-col gap-2 items-center" >
508514 < ModelSelect
509515 value = { selectedModel2 }
510- onChange = { setSelectedModel2 }
516+ onChange = { value => updateModelSlot ( 1 , value ) }
511517 availableModels = { getAvailableModelsForSlot ( 1 ) }
512518 />
513519 </ div >
0 commit comments