"use client" import { useState, useCallback } from "react" import { ImageIcon, Loader2, Search, ExternalLink } from "lucide-react" import { motion, AnimatePresence } from "motion/react" interface SteamGridResult { id: number name: string } interface SteamGridImage { id: number url: string thumb: string width: number height: number } interface NonSteamImageStepProps { headerImage: string capsuleImage: string onChange: (headerImage: string, capsuleImage: string) => void } export function NonSteamImageStep({ headerImage, capsuleImage, onChange, }: NonSteamImageStepProps) { const [query, setQuery] = useState("") const [searching, setSearching] = useState(false) const [loadingGrids, setLoadingGrids] = useState(false) const [results, setResults] = useState([]) const [grids, setGrids] = useState([]) const [selectedGameId, setSelectedGameId] = useState(null) const [manualUrl, setManualUrl] = useState("") const [showManual, setShowManual] = useState(false) const search = useCallback(async () => { if (!query.trim() || query.trim().length < 2) return setSearching(true) setResults([]) setGrids([]) setSelectedGameId(null) try { const res = await fetch(`/api/steamgrid/search?q=${encodeURIComponent(query)}`) if (!res.ok) throw new Error("Search failed") const data = await res.json() setResults((data.data || []).slice(0, 8)) } catch { setResults([]) } finally { setSearching(false) } }, [query]) const fetchGrids = useCallback(async (gameId: number) => { setLoadingGrids(true) setGrids([]) setSelectedGameId(gameId) try { const res = await fetch(`/api/steamgrid/grids/${gameId}?styles=alternate`) if (!res.ok) throw new Error("Failed to fetch grids") const data = await res.json() const images: SteamGridImage[] = (data.data || []) .filter((g: SteamGridImage) => g.url) .sort((a: SteamGridImage, b: SteamGridImage) => { // Prefer 600x900 const aScore = a.width === 600 && a.height === 900 ? 2 : a.width === 342 ? 1 : 0 const bScore = b.width === 600 && b.height === 900 ? 2 : b.width === 342 ? 1 : 0 return bScore - aScore }) setGrids(images.slice(0, 12)) } catch { setGrids([]) } finally { setLoadingGrids(false) } }, []) const handleSelectImage = (url: string) => { // Use the same image for both header and capsule onChange(url, url) } const handleManualSubmit = () => { if (!manualUrl.trim()) return onChange(manualUrl.trim(), manualUrl.trim()) } const currentImage = capsuleImage || headerImage return (

Cover Art

Search SteamGridDB for cover art, or paste an image URL manually.

{/* Search */}
setQuery(e.target.value)} onKeyDown={(e) => e.key === "Enter" && search()} placeholder="Search SteamGridDB..." className="w-full px-4 py-3 pr-10 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" />
{/* Results */} {results.length > 0 && ( {results.map((r) => ( ))} )} {/* Grid images */} {loadingGrids && (
)} {grids.length > 0 && !loadingGrids && ( {grids.map((g) => { const isSelected = capsuleImage === g.url return ( ) })} )}
{/* Manual URL */}
{showManual && ( setManualUrl(e.target.value)} placeholder="https://example.com/cover.jpg" className="w-full px-4 py-3 rounded-lg border border-border bg-text/5 text-text text-sm placeholder:text-text/40 outline-none focus:border-primary focus:ring-2 focus:ring-primary/50 transition-colors" /> )}
{/* Preview */} {currentImage && (

Selected Cover

{/* eslint-disable-next-line @next/next/no-img-element */} Selected cover
)}
) }