@@ -36,9 +36,11 @@ import { Link } from "wouter";
3636import { apiFetch , apiRequest } from "@/lib/queryClient" ;
3737import { getAddGamePendingQuery , clearAddGamePendingQuery } from "@/lib/add-game-store" ;
3838import { useIsMobile } from "@/hooks/use-mobile" ;
39+ import { resolveTargetPlatform } from "@shared/title-utils" ;
3940
4041interface SearchResult extends Game {
4142 inCollection ?: boolean ;
43+ platformOptions ?: IGDBPlatform [ ] ;
4244}
4345
4446interface AddGameModalProps {
@@ -58,6 +60,7 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
5860 const [ showUndatedGames , setShowUndatedGames ] = useState ( false ) ;
5961 const [ selectedPlatform , setSelectedPlatform ] = useState ( "all" ) ;
6062 const [ releaseYear , setReleaseYear ] = useState ( "" ) ;
63+ const [ targetPlatforms , setTargetPlatforms ] = useState < Record < string , string > > ( { } ) ;
6164 const { toast } = useToast ( ) ;
6265 const queryClient = useQueryClient ( ) ;
6366 const isMobile = useIsMobile ( ) ;
@@ -86,6 +89,11 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
8689 return ( ) => clearTimeout ( timer ) ;
8790 } , [ searchQuery ] ) ;
8891
92+ // Per-result target overrides only apply to the current discovery result set.
93+ useEffect ( ( ) => {
94+ setTargetPlatforms ( { } ) ;
95+ } , [ searchQuery , selectedPlatform , releaseYear , showUndatedGames ] ) ;
96+
8997 // Pre-fill search when modal opens (from prop or from the dashboard store)
9098 useEffect ( ( ) => {
9199 if ( open ) {
@@ -102,6 +110,7 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
102110 setShowUndatedGames ( false ) ;
103111 setSelectedPlatform ( "all" ) ;
104112 setReleaseYear ( "" ) ;
113+ setTargetPlatforms ( { } ) ;
105114 }
106115 } , [ open , initialQuery ] ) ;
107116
@@ -225,10 +234,65 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
225234 </ div >
226235 </ div >
227236 ) ;
237+ const getSupportedTargetOptions = ( game : SearchResult ) =>
238+ game . platformOptions ?. filter ( ( { id, name } ) => resolveTargetPlatform ( id , name ) ) ?? [ ] ;
239+
240+ const getTargetPlatformValue = ( game : SearchResult ) => {
241+ const supportedOptions = getSupportedTargetOptions ( game ) ;
242+ const key = String ( game . igdbId ?? game . id ) ;
243+ const explicitValue = targetPlatforms [ key ] ;
244+ if (
245+ explicitValue &&
246+ ( explicitValue === "default" ||
247+ supportedOptions . some ( ( { id } ) => String ( id ) === explicitValue ) )
248+ ) {
249+ return explicitValue ;
250+ }
251+ if (
252+ selectedPlatform !== "all" &&
253+ supportedOptions . some ( ( { id } ) => String ( id ) === selectedPlatform )
254+ ) {
255+ return selectedPlatform ;
256+ }
257+ return supportedOptions . length === 1 ? String ( supportedOptions [ 0 ] . id ) : "default" ;
258+ } ;
228259
260+ const renderTargetPlatformSelect = ( game : SearchResult ) => {
261+ const supportedOptions = getSupportedTargetOptions ( game ) ;
262+ if ( game . inCollection || ! supportedOptions ?. length ) return null ;
263+ const key = String ( game . igdbId ?? game . id ) ;
264+ return (
265+ < Select
266+ value = { getTargetPlatformValue ( game ) }
267+ onValueChange = { ( value ) => setTargetPlatforms ( ( current ) => ( { ...current , [ key ] : value } ) ) }
268+ >
269+ < SelectTrigger
270+ className = "h-8 w-full max-w-64 text-xs"
271+ aria-label = { `Target platform for ${ game . title } ` }
272+ >
273+ < SelectValue placeholder = "Account default" />
274+ </ SelectTrigger >
275+ < SelectContent >
276+ < SelectItem value = "default" > Account default</ SelectItem >
277+ { supportedOptions . map ( ( platform ) => (
278+ < SelectItem key = { platform . id } value = { String ( platform . id ) } >
279+ { platform . name }
280+ </ SelectItem >
281+ ) ) }
282+ </ SelectContent >
283+ </ Select >
284+ ) ;
285+ } ;
229286 const handleAddGame = ( searchResult : SearchResult ) => {
230- // Map to InsertGame to filter out client-only fields before sending to server
231- const gameData = mapGameToInsertGame ( searchResult ) ;
287+ const selectedTarget = getTargetPlatformValue ( searchResult ) ;
288+ const targetPlatform = searchResult . platformOptions ?. find (
289+ ( { id } ) => String ( id ) === selectedTarget
290+ ) ;
291+ const gameData = mapGameToInsertGame ( {
292+ ...searchResult ,
293+ targetPlatformId : targetPlatform ?. id ?? null ,
294+ targetPlatformName : targetPlatform ?. name ?? null ,
295+ } ) ;
232296 addGameMutation . mutate ( gameData ) ;
233297 } ;
234298
@@ -397,6 +461,8 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
397461 { game . summary }
398462 </ p >
399463 ) }
464+
465+ { renderTargetPlatformSelect ( game ) }
400466 </ div >
401467 </ div >
402468 ) ) }
@@ -527,6 +593,8 @@ export default function AddGameModal({ children, initialQuery }: AddGameModalPro
527593 ) ) }
528594 </ div >
529595
596+ { renderTargetPlatformSelect ( game ) }
597+
530598 < div className = "flex items-center justify-between" >
531599 < div className = "flex flex-wrap gap-1" >
532600 { game . platforms ?. slice ( 0 , 3 ) . map ( ( platform ) => (
0 commit comments