From 23fa7be89f960b9437c9ca81f2258f4811a7aab1 Mon Sep 17 00:00:00 2001
From: Adrian Bonpin
Date: Tue, 28 Apr 2026 23:24:33 +0800
Subject: [PATCH] feat: display system requirements and store stats on game
details page
---
app/game/[id]/game-page-client.tsx | 93 +++++++++++++++++++++++++++++-
app/game/[id]/page.tsx | 11 ++++
2 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/app/game/[id]/game-page-client.tsx b/app/game/[id]/game-page-client.tsx
index ef2dd1c..6ae4ec9 100644
--- a/app/game/[id]/game-page-client.tsx
+++ b/app/game/[id]/game-page-client.tsx
@@ -16,6 +16,7 @@ import {
ThumbsUpIcon,
ThumbsDownIcon,
GaugeIcon,
+ ChevronDownIcon,
} from "lucide-react"
import Link from "next/link"
import { useSession } from "@/lib/auth-client"
@@ -26,6 +27,7 @@ import type { GameSettingCategory } from "@/lib/db/schema/performanceEntries"
import { PresetDetailModal } from "./preset-detail-modal"
import { BookmarkButton } from "@/components/saved-games/bookmark-button"
+import { WindowsIcon, MacIcon, LinuxIcon } from "@/app/components/PlatformIcons"
// Chart imports
import { HistoricalAreaChart } from "@/components/charts/HistoricalAreaChart"
@@ -57,6 +59,17 @@ interface Game {
createdAt: string
metascore?: number | null
onlineMultiplayerStatus?: string | null
+ systemRequirements: { minimum: string | null; recommended: string | null } | null
+ metacriticScore: number | null
+ metacriticUrl: string | null
+ recommendationsTotal: number | null
+ priceCurrent: number | null
+ priceInitial: number | null
+ priceCurrency: string | null
+ isFree: boolean
+ releaseDate: string | null
+ categories: string[] | null
+ platforms: { windows: boolean; mac: boolean; linux: boolean } | null
}
interface Counts {
@@ -239,6 +252,7 @@ export function GamePageClient({
})
const [loading, setLoading] = useState(true)
const [selectedPresetId, setSelectedPresetId] = useState(null)
+ const [showSystemReq, setShowSystemReq] = useState(false)
const [reportedPresets, setReportedPresets] = useState>(new Set())
const presetsRef = useRef(null)
@@ -607,6 +621,33 @@ export function GamePageClient({
No description available.
)}
+ {game.systemRequirements && (game.systemRequirements.minimum || game.systemRequirements.recommended) && (
+
+
+ {showSystemReq && (
+
+ {game.systemRequirements.minimum && (
+
+ )}
+ {game.systemRequirements.recommended && (
+
+ )}
+
+ )}
+
+ )}
{/* Right: Metadata grid */}
@@ -639,9 +680,59 @@ export function GamePageClient({
value={game.onlineMultiplayerStatus}
/>
)}
+ {game.isFree && }
+ {game.priceCurrent != null && !game.isFree && game.priceCurrency && (
+
+ )}
+ {game.priceCurrent != null && !game.isFree && game.priceInitial != null && game.priceInitial > game.priceCurrent && game.priceCurrency && (
+
+ )}
+ {game.metacriticScore != null && (
+
+ )}
+ {game.recommendationsTotal != null && (
+
+ )}
+ {game.releaseDate && }
- {/* Platform Support */}
+ {/* Platforms */}
+ {game.platforms && (
+
+
+ Platforms
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
{platformSupport.length > 0 && (
diff --git a/app/game/[id]/page.tsx b/app/game/[id]/page.tsx
index 4c957c7..91e42c8 100644
--- a/app/game/[id]/page.tsx
+++ b/app/game/[id]/page.tsx
@@ -276,6 +276,17 @@ export default async function GamePage({
lastSync: game.lastSync ? game.lastSync.toISOString() : null,
syncStatus: game.syncStatus,
createdAt: game.createdAt.toISOString(),
+ systemRequirements: game.systemRequirements,
+ metacriticScore: game.metacriticScore,
+ metacriticUrl: game.metacriticUrl,
+ recommendationsTotal: game.recommendationsTotal,
+ priceCurrent: game.priceCurrent,
+ priceInitial: game.priceInitial,
+ priceCurrency: game.priceCurrency,
+ isFree: game.isFree,
+ releaseDate: game.releaseDate,
+ categories: game.categories,
+ platforms: game.platforms,
}
const serializedPresets = presetRows.map((p) => ({