"use client"; import Image from "next/image"; import { useEffect, useRef } from "react"; import type { GamePricePoint, GameProfile } from "@/lib/game/game-profile-types"; import { describeProfile, discountPercent, formatCount, formatPrice, formatRatingPercent, localizeScore, type ModalDict, } from "@/lib/game/game-format"; import { steamdbAppUrl } from "@/lib/game/discord-app"; export function ModalReviews({ profile, dict, localeTag, }: { profile: GameProfile; dict: ModalDict; localeTag: string; }) { const { dbRating, hasReviews, metascore, opencritic } = describeProfile(profile); if (!hasReviews) { return null; } const steamdbRating: { score: number; url: string } | null = dbRating != null && profile.steamId ? { score: dbRating, url: steamdbAppUrl(profile.steamId) } : null; return (

{dict.reviews}

{profile.steamReviews ? (

{dict.totalReviews}

{localizeScore(profile.steamReviews.label, dict)}

{formatCount(profile.steamReviews.total, localeTag, dict.reviewsUnit)}

) : null} {steamdbRating ? (

{dict.steamdbRating}

{formatRatingPercent(steamdbRating.score, localeTag)}

steamdb.info ↗

) : null} {metascore ? (

Metacritic

{metascore.score ?? "—"} {metascore.score != null ? ( /100 ) : null}

{formatCount(metascore.count, localeTag, dict.reviewsUnit)}

) : null} {opencritic ? (

OpenCritic

{opencritic.score ?? "—"} {opencritic.score != null ? ( /100 ) : null}

{formatCount(opencritic.count, localeTag, dict.reviewsUnit)}

) : null}
); } export function ModalPrices({ dict, localeTag, bestPrice, historyLow, isFree, }: { dict: ModalDict; localeTag: string; bestPrice: GamePricePoint | null; historyLow: GamePricePoint | null; isFree: boolean; }) { return (

{dict.prices}

{isFree ? (

{dict.free}

) : (
{bestPrice ? (

{dict.bestPrice} · {bestPrice.shop}

{formatPrice(bestPrice, localeTag)}{" "} {discountPercent(bestPrice) ? ( -%{discountPercent(bestPrice)} ) : null}

) : null} {historyLow ? (

{dict.historyLow} · {historyLow.shop}

{formatPrice(historyLow, localeTag)}

) : null}
)}
); } export function ModalScreenshots({ profile, dict, hero, onPick, }: { profile: GameProfile; dict: ModalDict; hero: string | null; onPick: (shot: string) => void; }) { const stripRef = useRef(null); useEffect(() => { const strip = stripRef.current; if (!strip) { return; } function onWheel(event: WheelEvent): void { const el = stripRef.current; if (!el) { return; } if (Math.abs(event.deltaX) >= Math.abs(event.deltaY)) { return; } if (el.scrollWidth <= el.clientWidth + 1) { return; } event.preventDefault(); el.scrollLeft += event.deltaY; } strip.addEventListener("wheel", onWheel, { passive: false }); return () => strip.removeEventListener("wheel", onWheel); }, [profile]); function scrollStrip(by: number): void { stripRef.current?.scrollBy({ left: by, behavior: "smooth" }); } return (

{dict.screenshots}

{profile.screenshots.map((shot) => ( ))}
); }