diff --git a/app/page.tsx b/app/page.tsx index a7e67c3..5c1ef9c 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -35,6 +35,15 @@ interface SectionData { recentBenchmarks: GameCard[] trending: GameCard[] mostTested: GameCard[] + onSale: SaleGameCard[] +} + +interface SaleGameCard extends GameCard { + price_current?: number + price_initial?: number + price_currency?: string + steam_review_score?: number + best_fps?: number } function SkeletonSections() { @@ -196,6 +205,138 @@ function GameSection({ ) } +function SaleSection({ + games, +}: { + games: SaleGameCard[] +}) { + const router = useRouter() + + return ( + +
+
+
+ 💰 +

+ On Sale & Performing Well +

+
+
+
+ +
+ {games.map((game, idx) => { + const discountPct = game.price_initial && game.price_current + ? Math.round((1 - game.price_current / game.price_initial) * 100) + : 0 + + return ( + router.push(`/game/${game.id}?sync=1`)} + > +
+ {game.capsule_image ? ( + {game.title} + ) : ( +
+ +
+ )} + {/* Discount badge */} + {discountPct > 0 && ( +
+ -{discountPct}% +
+ )} + {game.playability_status && + game.playability_status !== "unknown" && ( +
+ +
+ )} +
+ +
+

+ {game.title} +

+ + {/* Pricing */} +
+ {game.price_current !== undefined && ( + + {game.price_currency === "USD" ? "$" : ""}{(game.price_current / 100).toFixed(2)} + + )} + {game.price_initial !== undefined && game.price_initial > (game.price_current ?? 0) && ( + + {(game.price_initial / 100).toFixed(2)} + + )} +
+ + {/* Performance badges */} + {game.best_fps !== undefined && game.best_fps !== null && ( +
+ {game.best_fps >= 60 ? ( + + âš¡ RAW PERFORMER + + ) : game.best_fps < 30 ? ( + + âš  POOR PERFORMANCE + + ) : null} + + {Math.round(game.best_fps)}fps + +
+ )} + + {game.steam_review_score !== undefined && game.steam_review_score !== null && ( +

+ {game.steam_review_score}% positive +

+ )} +
+
+ ) + })} +
+ + {/* Disclaimer */} +

+ Prices may vary. Data refreshes weekly. +

+
+ ) +} + export default function Landing() { const router = useRouter() const words = ["benchmarks", "settings", "reviews"] @@ -208,6 +349,7 @@ export default function Landing() { recentBenchmarks: [], trending: [], mostTested: [], + onSale: [], }) const [sectionsLoading, setSectionsLoading] = useState(true) @@ -224,7 +366,7 @@ export default function Landing() { let cancelled = false async function fetchSections() { try { - const [recentBenchmarks, trending, mostTested] = + const [recentBenchmarks, trending, mostTested, onSale] = await Promise.all([ fetch("/api/dashboard/recent-benchmarks").then((r) => r.ok ? r.json() : [], @@ -235,12 +377,16 @@ export default function Landing() { fetch("/api/dashboard/most-tested").then((r) => r.ok ? r.json() : [], ), + fetch("/api/dashboard/on-sale").then((r) => + r.ok ? r.json() : [], + ), ]) if (!cancelled) { setSections({ recentBenchmarks: Array.isArray(recentBenchmarks) ? recentBenchmarks : [], trending: Array.isArray(trending) ? trending : [], mostTested: Array.isArray(mostTested) ? mostTested : [], + onSale: Array.isArray(onSale) ? onSale : [], }) } } catch { @@ -411,6 +557,9 @@ export default function Landing() { accentColor='text-blue-400' /> )} + {sections.onSale.length > 0 && ( + + )} )}