96 lines
4.8 KiB
TypeScript
96 lines
4.8 KiB
TypeScript
import { redirect, notFound } from "next/navigation";
|
||
import Link from "next/link";
|
||
import { auth } from "@/auth";
|
||
import { prisma } from "@/lib/prisma";
|
||
import { creditTicker } from "@/lib/credits-brand";
|
||
import { SiteFooter } from "@/components/SiteFooter";
|
||
import { ExchangePanel } from "@/components/casino/ExchangePanel";
|
||
import { CrashGame } from "@/components/casino/CrashGame";
|
||
import { DiceGame } from "@/components/casino/DiceGame";
|
||
import { MinesGame } from "@/components/casino/MinesGame";
|
||
import { TowerGame } from "@/components/casino/TowerGame";
|
||
import { SlotsGame } from "@/components/casino/SlotsGame";
|
||
import { BlackjackGame } from "@/components/casino/BlackjackGame";
|
||
import { RouletteGame } from "@/components/casino/RouletteGame";
|
||
import { CoinFlipRoom } from "@/components/casino/CoinFlipRoom";
|
||
import { PongGame } from "@/components/casino/PongGame";
|
||
import { PredictionMarket } from "@/components/casino/PredictionMarket";
|
||
|
||
const T = creditTicker();
|
||
|
||
const GAME_META: Record<string, { name: string; icon: string; desc: string }> = {
|
||
crash: { name: `${T} Crash`, icon: "📈", desc: "Multiplier rises from 1x — cash out before it crashes. Provably fair." },
|
||
dice: { name: "Dice Roll", icon: "🎲", desc: "Pick over or under a threshold. Adjust your risk and win chance live." },
|
||
mines: { name: "Mines", icon: "💣", desc: "5×5 grid — reveal tiles to grow your multiplier and cash out before hitting a mine." },
|
||
tower: { name: "Tower Climb", icon: "🏰", desc: "Pick a safe tile on each floor to climb higher and earn bigger multipliers." },
|
||
slots: { name: "Slots", icon: "🎰", desc: "3-reel classic slot machine with configurable seeds and a full paytable." },
|
||
blackjack: { name: "Blackjack", icon: "🃏", desc: "Classic single-deck blackjack. Hit, stand, or double down against the house." },
|
||
roulette: { name: "Roulette", icon: "🎡", desc: "European roulette (single zero). Bet on numbers, colors, dozens, and more." },
|
||
coinflip: { name: "Coin Flip Duel", icon: "🪙", desc: "Create or join a room. Both players wager the same amount — the flip decides." },
|
||
pong: { name: "PvP Pong", icon: "🏓", desc: `Real-time pong against another player. Bet ${T} — first to 5 wins the pot.` },
|
||
prediction: { name: "Prediction Market", icon: "📊", desc: `Post a yes/no question. Users pool ${T} — correct side splits the pot.` },
|
||
};
|
||
|
||
export default async function GamePage({ params }: { params: Promise<{ game: string }> }) {
|
||
const { game } = await params;
|
||
const meta = GAME_META[game];
|
||
if (!meta) notFound();
|
||
|
||
const session = await auth();
|
||
if (!session?.user?.id) redirect(`/login?callbackUrl=${encodeURIComponent(`/casino/${game}`)}`);
|
||
|
||
const wallet = await prisma.wallet.findUnique({ where: { userId: session.user.id } });
|
||
const balance = wallet?.balanceCredits ?? 0;
|
||
const userId = session.user.id;
|
||
|
||
function GameComponent() {
|
||
switch (game) {
|
||
case "crash": return <CrashGame balance={balance} />;
|
||
case "dice": return <DiceGame balance={balance} />;
|
||
case "mines": return <MinesGame balance={balance} />;
|
||
case "tower": return <TowerGame balance={balance} />;
|
||
case "slots": return <SlotsGame balance={balance} />;
|
||
case "blackjack": return <BlackjackGame balance={balance} />;
|
||
case "roulette": return <RouletteGame balance={balance} />;
|
||
case "coinflip": return <CoinFlipRoom userId={userId} balance={balance} />;
|
||
case "pong": return <PongGame userId={userId} balance={balance} />;
|
||
case "prediction": return <PredictionMarket userId={userId} balance={balance} />;
|
||
default: return null;
|
||
}
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<main className="min-h-screen bg-[#030712] px-4 py-8 sm:px-6">
|
||
<div className="mx-auto max-w-6xl">
|
||
<div className="flex items-center gap-3 mb-6">
|
||
<Link href="/casino" className="text-slate-400 hover:text-white transition-colors text-sm">
|
||
← Casino
|
||
</Link>
|
||
<span className="text-slate-600">/</span>
|
||
<span className="text-white font-medium">{meta.name}</span>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||
<div className="space-y-4">
|
||
<ExchangePanel initialBalance={balance} />
|
||
<div className="rounded-2xl border border-white/10 bg-white/5 p-5">
|
||
<div className="flex items-center gap-3 mb-2">
|
||
<span className="text-3xl">{meta.icon}</span>
|
||
<h1 className="text-xl font-bold text-white">{meta.name}</h1>
|
||
</div>
|
||
<p className="text-slate-400 text-sm">{meta.desc}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="lg:col-span-2 rounded-2xl border border-white/10 bg-white/5 p-5">
|
||
<GameComponent />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
<SiteFooter />
|
||
</>
|
||
);
|
||
}
|