This commit is contained in:
Gavin McDonald
2025-04-12 15:17:02 -04:00
parent 1734eec436
commit 6508d40b2d
19 changed files with 1415 additions and 1344 deletions

View File

@@ -1,68 +1,72 @@
"use client";
'use client';
import { useEffect, useState } from "react";
import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import { socket } from "@/socket";
import { socket } from '@/socket';
import Card from '@/components/Card';
import type { GameUpdate, ClientUpdate, StandardGameCard, TarokkaGameCard } from '@/types';
export default function GamePage() {
const { gameID: gameIDParam } = useParams();
const { gameID: gameIDParam } = useParams();
const [gameID, setGameID] = useState('');
const [cards, setCards] = useState<StandardGameCard[] | TarokkaGameCard[]>([]);
const [gameID, setGameID] = useState('');
const [cards, setCards] = useState<StandardGameCard[] | TarokkaGameCard[]>([]);
useEffect(() => {
if (gameIDParam) {
setGameID(Array.isArray(gameIDParam) ? gameIDParam[0] : gameIDParam);
}
}, [gameIDParam])
useEffect(() => {
if (gameIDParam) {
setGameID(Array.isArray(gameIDParam) ? gameIDParam[0] : gameIDParam);
}
}, [gameIDParam]);
useEffect(() => {
if (gameID) {
socket.emit('join', gameID);
useEffect(() => {
if (gameID) {
socket.emit('join', gameID);
socket.on('init', (data: GameUpdate) => {
console.log('init', data);
setCards(data.cards);
});
socket.on('init', (data: GameUpdate) => {
console.log('init', data);
setCards(data.cards);
});
socket.on('card-flipped', (data: GameUpdate) => {
console.log('>>>', data);
setCards(data.cards);
});
}
socket.on('card-flipped', (data: GameUpdate) => {
console.log('>>>', data);
setCards(data.cards);
});
}
return gameID ? () => {
socket.off('init');
socket.off('card-flipped');
} : undefined;
}, [gameID]);
return gameID
? () => {
socket.off('init');
socket.off('card-flipped');
}
: undefined;
}, [gameID]);
const flipCard = (cardIndex: number) => {
const flip: ClientUpdate = {
gameID,
cardIndex,
};
const flipCard = (cardIndex: number) => {
const flip: ClientUpdate = {
gameID,
cardIndex,
};
socket.emit('flip-card', flip);
};
socket.emit('flip-card', flip);
};
return cards.length ? (
<main className="min-h-screen flex flex-col items-center justify-center gap-4 bg-[url('/img/table3.png')] bg-cover bg-center">
<div className="grid grid-cols-3 grid-rows-3 gap-8 w-fit mx-auto">
{Array.from({ length: 9 }).map((_, i) => {
const cardIndex = [1, 3, 4, 5, 7].indexOf(i);
return cards.length ? (
<main className="min-h-screen flex flex-col items-center justify-center gap-4 bg-[url('/img/table3.png')] bg-cover bg-center">
<div className="grid grid-cols-3 grid-rows-3 gap-8 w-fit mx-auto">
{Array.from({ length: 9 }).map((_, i) => {
const cardIndex = [1, 3, 4, 5, 7].indexOf(i);
return (
<div key={i} className="aspect-[2/3]}">
{cardIndex !== -1 && <Card card={cards[cardIndex]} flipAction={() => flipCard(cardIndex)} />}
</div>
)
})}
</div>
</main>
) : null;
return (
<div key={i} className="aspect-[2/3]}">
{cardIndex !== -1 && (
<Card card={cards[cardIndex]} flipAction={() => flipCard(cardIndex)} />
)}
</div>
);
})}
</div>
</main>
) : null;
}

View File

@@ -1,3 +0,0 @@
export default function B() {
return <div>b</div>;
}

View File

@@ -1,26 +1,26 @@
@import "tailwindcss";
@import 'tailwindcss';
:root {
--background: #ffffff;
--foreground: #171717;
--background: #ffffff;
--foreground: #171717;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
background: var(--background);
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}

View File

@@ -1,34 +1,30 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
variable: '--font-geist-sans',
subsets: ['latin'],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
variable: '--font-geist-mono',
subsets: ['latin'],
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: 'Create Next App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
children,
}: Readonly<{
children: React.ReactNode;
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
return (
<html lang="en">
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>{children}</body>
</html>
);
}

View File

@@ -3,22 +3,21 @@ import { useRouter } from 'next/navigation';
import generateID from '@/tools/simpleID';
export default function Home() {
const router = useRouter();
const router = useRouter();
const handleCreateGame = () => {
const id = generateID();
router.push(`/${id}`);
};
const handleCreateGame = () => {
const id = generateID();
router.push(`/${id}`);
};
return (
<main className="min-h-screen flex items-center justify-center bg-[url('/img/table3.png')] bg-cover bg-center">
<button
onClick={handleCreateGame}
className="bg-blue-600 text-white text-lg px-6 py-3 rounded-xl shadow hover:bg-blue-700 transition"
>
Create New Game
</button>
</main>
);
return (
<main className="min-h-screen flex items-center justify-center bg-[url('/img/table3.png')] bg-cover bg-center">
<button
onClick={handleCreateGame}
className="bg-blue-600 text-white text-lg px-6 py-3 rounded-xl shadow hover:bg-blue-700 transition"
>
Create New Game
</button>
</main>
);
}