import type { ReactNode } from "react"; import { getIntegrationConfig, getProfile } from "@/lib/integrations"; import { SOCIAL_NETWORKS } from "@/lib/integrations/social"; import type { SocialLink } from "@/lib/integrations/types"; import { saveIntegrationsAction, refreshIntegrationsAction, testIntegrationAction, } from "../../actions"; import ConsolePicker from "./ConsolePicker"; import GamePicker from "./GamePicker"; // Expandable "how do I get this?" help, shown under credential fields. Uses a // native
so it works with zero JS and stays readable on mobile. function CredHelp({ title, children }: { title: string; children: ReactNode }) { return (
ⓘ {title}
{children}
); } // A "Test connection" submit button. Submits the whole form to the test action // (so it validates the live, unsaved field values) tagged with which platform. function TestButton({ platform }: { platform: string }) { return ( ); } function socialToText(links: SocialLink[]): string { return links .map((l) => [l.network, l.url, l.label].filter(Boolean).join(" | ")) .join("\n"); } function fmtAge(iso: string): string { const t = new Date(iso).getTime(); if (Number.isNaN(t)) return "—"; const mins = Math.round((Date.now() - t) / 60000); if (mins < 1) return "just now"; if (mins < 60) return `${mins} min ago`; const hrs = Math.round(mins / 60); return hrs < 24 ? `${hrs}h ago` : `${Math.round(hrs / 24)}d ago`; } type Banners = { saved?: string; refreshed?: string; steam?: string; steamErr?: string; test?: string; testErr?: string; testGames?: string; testNotice?: string; }; function Banner(p: Banners) { if (p.saved) return

Integrations saved. Caches cleared.

; if (p.refreshed) return

Platform caches cleared — data refetches on next view.

; if (p.steam) return (

Steam linked — SteamID {p.steam} saved. Add your API key below to pull game data.

); if (p.steamErr) return

{p.steamErr}

; if (p.test && p.testErr) return (

{p.test.toUpperCase()} test failed: {p.testErr}

); if (p.test) return (

{p.test.toUpperCase()} connection OK — fetched {p.testGames ?? 0} game(s). {p.testNotice ? ` ${p.testNotice}` : ""}

); return null; } export default async function IntegrationsPage({ searchParams, }: { searchParams: Promise; }) { const banners = await searchParams; const cfg = getIntegrationConfig(); // Loads (cached) platform data so we can show freshness + any fetch errors. const profile = await getProfile(); const networkIds = SOCIAL_NETWORKS.map((n) => n.id).join(", "); return (

Integrations

Build your gamer bio: a profile, social links, console list, favorite games, and live data pulled from gaming platforms. Everything here powers the public bio page.

{/* ---- platform status ---- */} {profile.platforms.length > 0 && (

Platform status

{profile.platforms.map((p) => ( ))}
Platform Games Achievements Fetched Status
{p.platform.toUpperCase()} {p.games.length} {p.achievements.length} {fmtAge(p.fetchedAt)} {p.error ? ( {p.error} ) : ( "OK" )}
)}
{/* ---- profile ---- */}

Profile