11import { Badge } from "@renderer/components" ;
22import { buildGameDetailsPath } from "@renderer/helpers" ;
3- import { useAppSelector , useRepacks } from "@renderer/hooks" ;
4- import { useMemo } from "react" ;
3+ import { useAppSelector , useRepacks , useLibrary } from "@renderer/hooks" ;
4+ import { useMemo , useState , useEffect } from "react" ;
55import { useNavigate } from "react-router-dom" ;
66
77import "./game-item.scss" ;
88import { useTranslation } from "react-i18next" ;
99import { CatalogueSearchResult } from "@types" ;
10- import { QuestionIcon } from "@primer/octicons-react" ;
10+ import { QuestionIcon , PlusIcon , CheckIcon } from "@primer/octicons-react" ;
11+ import cn from "classnames" ;
1112
1213export interface GameItemProps {
1314 game : CatalogueSearchResult ;
@@ -16,15 +17,49 @@ export interface GameItemProps {
1617export function GameItem ( { game } : GameItemProps ) {
1718 const navigate = useNavigate ( ) ;
1819
19- const { i18n } = useTranslation ( ) ;
20+ const { i18n, t } = useTranslation ( "game_details" ) ;
21+
22+ const language = i18n . language . split ( "-" ) [ 0 ] ;
2023
2124 const { steamGenres } = useAppSelector ( ( state ) => state . catalogueSearch ) ;
2225
2326 const { getRepacksForObjectId } = useRepacks ( ) ;
2427
2528 const repacks = getRepacksForObjectId ( game . objectId ) ;
2629
27- const language = i18n . language . split ( "-" ) [ 0 ] ;
30+ const [ isAddingToLibrary , setIsAddingToLibrary ] = useState ( false ) ;
31+
32+ const [ added , setAdded ] = useState ( false ) ;
33+
34+ const { library, updateLibrary } = useLibrary ( ) ;
35+
36+ useEffect ( ( ) => {
37+ const exists = library . some (
38+ ( libItem ) =>
39+ libItem . shop === game . shop && libItem . objectId === game . objectId
40+ ) ;
41+ setAdded ( exists ) ;
42+ } , [ library , game . shop , game . objectId ] ) ;
43+
44+ const addGameToLibrary = async ( event : React . MouseEvent | React . KeyboardEvent ) => {
45+ event . stopPropagation ( ) ;
46+ if ( added || isAddingToLibrary ) return ;
47+
48+ setIsAddingToLibrary ( true ) ;
49+
50+ try {
51+ await window . electron . addGameToLibrary (
52+ game . shop ,
53+ game . objectId ,
54+ game . title
55+ ) ;
56+ updateLibrary ( ) ;
57+ } catch ( error ) {
58+ console . error ( error ) ;
59+ } finally {
60+ setIsAddingToLibrary ( false ) ;
61+ }
62+ } ;
2863
2964 const uniqueRepackers = useMemo ( ( ) => {
3065 return Array . from ( new Set ( repacks . map ( ( repack ) => repack . repacker ) ) ) ;
@@ -85,6 +120,23 @@ export function GameItem({ game }: GameItemProps) {
85120 ) ) }
86121 </ div >
87122 </ div >
123+ < div
124+ className = { cn ( "game-item__plus-wrapper" , {
125+ "game-item__plus-wrapper--added" : added ,
126+ } ) }
127+ role = "button"
128+ tabIndex = { 0 }
129+ onClick = { addGameToLibrary }
130+ onKeyDown = { ( e ) => {
131+ if ( e . key === "Enter" || e . key === " " ) {
132+ e . preventDefault ( ) ;
133+ addGameToLibrary ( e ) ;
134+ }
135+ } }
136+ title = { added ? t ( "already_in_library" ) : t ( "add_to_library" ) }
137+ >
138+ { added ? < CheckIcon size = { 16 } /> : < PlusIcon size = { 16 } /> }
139+ </ div >
88140 </ button >
89141 ) ;
90142}
0 commit comments