Add Democratic fundraising platform.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
root
2026-05-16 00:47:44 +00:00
parent 89f9b8dc83
commit 391d90a754
141 changed files with 14989 additions and 914 deletions

View File

@@ -0,0 +1,95 @@
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 />
</>
);
}