import { useState, useEffect } from 'react' import { findBestGameImage } from '@/services/ImageService' import { Game } from '@/types' import { ActionButton, ActionType, Button } from '@/components/buttons' import { Icon } from '@/components/icons' interface GameItemProps { game: Game onAction: (gameId: string, action: ActionType) => Promise onEdit?: (gameId: string) => void onSmokeAPISettings?: (gameId: string) => void } /** * Individual game card component * Displays game information and action buttons */ const GameItem = ({ game, onAction, onEdit, onSmokeAPISettings }: GameItemProps) => { const [imageUrl, setImageUrl] = useState(null) const [isLoading, setIsLoading] = useState(true) const [hasError, setHasError] = useState(false) useEffect(() => { // Function to fetch the game cover/image const fetchGameImage = async () => { // First check if we already have it (to prevent flickering on re-renders) if (imageUrl) return setIsLoading(true) try { // Try to find the best available image for this game const bestImageUrl = await findBestGameImage(game.id) if (bestImageUrl) { setImageUrl(bestImageUrl) setHasError(false) } else { setHasError(true) } } catch (error) { console.error('Error fetching game image:', error) setHasError(true) } finally { setIsLoading(false) } } if (game.id) { fetchGameImage() } }, [game.id, imageUrl]) // Determine if we should show CreamLinux buttons (only for native games) const shouldShowCream = game.native && game.cream_installed // Only show if installed (for uninstall) // Determine if we should show SmokeAPI buttons (only for non-native games with API files) const shouldShowSmoke = !game.native && game.api_files && game.api_files.length > 0 // Show generic button if nothing installed const shouldShowUnlocker = game.native && !game.cream_installed && !game.smoke_installed // Check if this is a Proton game without API files const isProtonNoApi = !game.native && (!game.api_files || game.api_files.length === 0) const handleCreamAction = () => { if (game.installing) return const action: ActionType = game.cream_installed ? 'uninstall_cream' : 'install_cream' onAction(game.id, action) } const handleSmokeAction = () => { if (game.installing) return const action: ActionType = game.smoke_installed ? 'uninstall_smoke' : 'install_smoke' onAction(game.id, action) } const handleUnlockerAction = () => { if (game.installing) return onAction(game.id, 'install_unlocker') } // Handle edit button click const handleEdit = () => { if (onEdit && game.cream_installed) { onEdit(game.id) } } // SmokeAPI settings handler const handleSmokeAPISettings = () => { if (onSmokeAPISettings && game.smoke_installed) { onSmokeAPISettings(game.id) } } // Determine background image const backgroundImage = !isLoading && imageUrl ? `url(${imageUrl})` : hasError ? 'linear-gradient(135deg, #232323, #1A1A1A)' : 'linear-gradient(135deg, #232323, #1A1A1A)' return (
{game.native ? 'Native' : 'Proton'} {game.cream_installed && CreamLinux} {game.smoke_installed && SmokeAPI}

{game.title}

{/* Show generic "Install" button for native games with nothing installed */} {shouldShowUnlocker && ( )} {/* Show CreamLinux uninstall button if CreamLinux is installed */} {shouldShowCream && ( )} {/* Show SmokeAPI button for Proton games OR native games with SmokeAPI installed */} {shouldShowSmoke && ( )} {/* Show SmokeAPI uninstall for native games if installed */} {game.native && game.smoke_installed && ( )} {/* Show message for Proton games without API files */} {isProtonNoApi && (
Steam API DLL not found
)} {/* Edit button - only enabled if CreamLinux is installed */} {game.cream_installed && (
) } export default GameItem