Files
whattoplay/src/client/features/games/components/game-list-item.tsx

64 lines
1.7 KiB
TypeScript

import { ListItem } from "@/shared/components/ui/list-item"
import type { Game } from "@/shared/db/schema"
import { formatPlaytime } from "../schema"
import { gameStateColors } from "../schema"
const apiBase = import.meta.env.BASE_URL.replace(/\/$/, "")
interface GameListItemProps {
game: Game
onClick?: () => void
}
export function GameListItem({ game, onClick }: GameListItemProps) {
const coverUrl = game.cover_image_id
? `${apiBase}/api/igdb/image/${game.cover_image_id}/thumb`
: game.source === "steam"
? `${apiBase}/api/steam/icon/${game.source_id}`
: undefined
const imgClass = game.cover_image_id
? "h-10 w-10 rounded object-cover"
: "h-10 w-16 rounded object-cover"
return (
<ListItem
link
title={game.title}
subtitle={
game.playtime_hours > 0
? formatPlaytime(game.playtime_hours)
: undefined
}
media={
coverUrl ? (
<img src={coverUrl} alt="" className={imgClass} />
) : (
<span className="flex h-10 w-10 items-center justify-center rounded bg-muted text-[10px] font-medium text-muted-foreground">
{game.source.toUpperCase()}
</span>
)
}
after={<GameListItemAfter game={game} />}
onClick={onClick}
/>
)
}
function GameListItemAfter({ game }: { game: Game }) {
const ratingText =
game.rating >= 0 ? `${Math.round(game.rating / 2)}/5` : null
const dotColor =
game.game_state !== "not_set" ? gameStateColors[game.game_state] : null
return (
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
{ratingText && <span>{ratingText}</span>}
{dotColor && (
<span className={`inline-block h-2 w-2 rounded-full ${dotColor}`} />
)}
{game.is_favorite && <span className="text-red-500"></span>}
</span>
)
}