SPB Git forge

spb/spinza

Public
8commits 1branches 0releases
1.6 MBsize
maindefault branch
16 days agolast push
TypeScript 97.6% SQL 1.4% JavaScript 0.5%
1.7 KB · 43 lines tsx
Raw Blame History
1import { Suspense } from "react";2import type { Metadata } from "next";3import type { GameCard } from "@spinza/shared";4import { apiServer } from "@/lib/api-server";5import { AppShell } from "@/components/shell/app-shell";6import { ServerUnavailable } from "@/components/shell/api-error";7import { GamesBrowser } from "@/components/lobby/games-browser";8import { GameCardSkeleton } from "@/components/lobby/game-card";910export const metadata: Metadata = {11  title: "Games",12  description: "Browse all twenty original Spinza games — cascades, expanding wilds, hold-and-respin jackpots and more. Free fictional credits, no cash value.",13  alternates: { canonical: "/games" },14};1516export default async function GamesPage() {17  const data = await apiServer<{ games: GameCard[] }>("/api/games");18  return (19    <AppShell>20      <div className="mb-6">21        <div className="eyebrow mb-1">Library</div>22        <h1 className="text-3xl font-semibold tracking-tight sm:text-4xl">All games</h1>23        <p className="mt-2 max-w-xl text-sm text-fg-3">Every title is a Spinza original, certified against its published math. Volatility tells you how the ride feels; open Game Info inside any game for the full details.</p>24      </div>25      {data === null ? (26        <ServerUnavailable />27      ) : (28        <Suspense29          fallback={30            <div className="grid grid-cols-2 gap-x-3 gap-y-6 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5" aria-busy>31              {Array.from({ length: 10 }).map((_, i) => (32                <GameCardSkeleton key={i} className="w-full sm:w-full" />33              ))}34            </div>35          }36        >37          <GamesBrowser games={data.games} />38        </Suspense>39      )}40    </AppShell>41  );42}43