Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added .Jules/palette.md
Empty file.
38 changes: 27 additions & 11 deletions src/components/Library/GameDetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,12 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
onClick={(e) => { e.stopPropagation(); onFavoriteToggle(); }}
className="absolute -top-2 -right-2 w-10 h-10 flex items-center justify-center text-3xl transition-transform hover:scale-110"
title={game.is_favorite ? t('removeFromFavorites') : t('addToFavorites')}
aria-label={game.is_favorite ? t('removeFromFavorites') : t('addToFavorites')}
>
{game.is_favorite ? (
<span className="text-yellow-400 drop-shadow-lg">★</span>
<span className="text-yellow-400 drop-shadow-lg" aria-hidden="true">★</span>
) : (
<span className="text-gray-400 hover:text-yellow-300">☆</span>
<span className="text-gray-400 hover:text-yellow-300" aria-hidden="true">☆</span>
)}
</button>
)}
Expand Down Expand Up @@ -234,20 +235,21 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
{game.igdb_id && (
<button type="button" onClick={handleOpenIgdb}
className="text-blue-400 hover:text-blue-300 text-sm px-3 py-1.5 bg-blue-900/40 rounded-lg hover:bg-blue-900/60 transition-colors inline-flex items-center gap-1">
🌐 {t('igdbPage')}
<span aria-hidden="true">🌐</span> {t('igdbPage')} <span aria-hidden="true">↗</span>
</button>
)}

{/* Folder path */}
<p
className="theme-text-muted text-sm font-mono cursor-pointer hover:text-blue-400 hover:underline transition-colors flex items-center gap-1"
<button
type="button"
className="theme-text-muted text-sm font-mono cursor-pointer hover:text-blue-400 hover:underline transition-colors flex items-center gap-1 w-full text-left bg-transparent border-0 p-0"
onClick={handleOpenFolder}
title={t('openFolder') || "Click to open folder"}
>
<span>📁</span>
<span aria-hidden="true">📁</span>
<span className="truncate">{game.folder_path}</span>
<span className="text-xs opacity-50">↗</span>
</p>
<span className="text-xs opacity-50" aria-hidden="true">↗</span>
</button>

{/* Status badges */}
<div className="flex items-center gap-2 flex-wrap">
Expand Down Expand Up @@ -364,11 +366,25 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
{/* Personal Rating */}
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="theme-text-muted text-sm">{t('personalRating')} (0-100): <span className="text-purple-500 font-semibold">{game.personal_rating !== null && game.personal_rating !== undefined ? `${game.personal_rating}/100` : '-'}</span></span>
<label htmlFor="personal-rating-slider" className="theme-text-muted text-sm">
{t('personalRating')} (0-100): <span className="text-purple-500 font-semibold">{game.personal_rating !== null && game.personal_rating !== undefined ? `${game.personal_rating}/100` : '-'}</span>
</label>
{game.personal_rating !== null && game.personal_rating !== undefined && (
<button
type="button"
onClick={() => onRatingChange?.(null)}
className="text-xs text-red-400 hover:text-red-300 transition-colors flex items-center gap-1"
title={t('clearRating')}
aria-label={t('clearRating')}
>
<span aria-hidden="true">✕</span> {t('clearRating')}
</button>
)}
</div>
<div className="flex items-center gap-3">
<span className="text-xs theme-text-muted">0</span>
<span className="text-xs theme-text-muted" aria-hidden="true">0</span>
<input
id="personal-rating-slider"
type="range"
min="0"
max="100"
Expand All @@ -390,7 +406,7 @@ export function GameDetailHeader({ game, onGameUpdated, onPlatformChange, onFilt
[&::-moz-range-thumb]:cursor-pointer
[&::-moz-range-thumb]:border-0"
/>
<span className="text-xs theme-text-muted">100</span>
<span className="text-xs theme-text-muted" aria-hidden="true">100</span>
</div>
</div>

Expand Down
2 changes: 0 additions & 2 deletions src/components/Library/GameScreenshotsCarousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function GameScreenshotsCarousel({ gameId }: GameScreenshotsCarouselProps
const [igdbScreenshots, setIgdbScreenshots] = useState<string[]>([]);
const [currentIndex, setCurrentIndex] = useState(0);
const [loading, setLoading] = useState(true);
const [hasIgdbId, setHasIgdbId] = useState(false);

useEffect(() => {
const loadScreenshots = async () => {
Expand All @@ -29,7 +28,6 @@ export function GameScreenshotsCarousel({ gameId }: GameScreenshotsCarouselProps
// Load game data to check IGDB ID
try {
const game = await invoke<{ igdb_id: number | null }>("get_game_by_id", { id: gameId });
setHasIgdbId(!!game?.igdb_id);

// Load IGDB screenshots if available
if (game?.igdb_id) {
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const translations = {

// Game Detail
personalRating: 'Personal Rating',
clearRating: 'Clear Rating',
notes: 'Notes',
saveNotes: 'Save Notes',
deleteGame: 'Delete Game',
Expand Down Expand Up @@ -291,7 +292,7 @@ export const translations = {
playTime: 'Play Time',
hours: 'hours',
platform: 'Platform',
platforms: 'Plateformes',
platforms: 'Platforms',
selectPlatform: 'Select platform...',
noPlatform: 'No platform',
availableOnIGDB: 'Available on',
Expand Down Expand Up @@ -435,6 +436,7 @@ export const translations = {

// Game Detail
personalRating: 'Note personnelle',
clearRating: 'Effacer la note',
notes: 'Notes',
saveNotes: 'Sauvegarder les notes',
deleteGame: 'Supprimer le jeu',
Expand Down