refactoring game for separate folders for game boards and common logic for player
This commit is contained in:
@@ -1,16 +1,14 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
import Board from "./Board";
|
||||
import Player from "./Player";
|
||||
import { PlayerModel } from "./Board";
|
||||
import { PlayerModel } from "./models/player";
|
||||
|
||||
export default function TicTacToe() {
|
||||
const [board, setBoard] = useState<string[][]>([
|
||||
["", "", ""],
|
||||
["", "", ""],
|
||||
["", "", ""]
|
||||
]);
|
||||
import TicTacToeBoard from "./games/tictactoe/TicTacToeBoard";
|
||||
|
||||
export default function App() {
|
||||
// setting up a 2D game board
|
||||
const [board, setBoard] = useState<string[][]>([[]]);
|
||||
const [turn, setTurn] = useState<number>(0);
|
||||
const [winner, setWinner] = useState<string | null>(null);
|
||||
const [gameOver, setGameOver] = useState<boolean | null>(null);
|
||||
@@ -115,7 +113,7 @@ export default function TicTacToe() {
|
||||
minWidth: "300px",
|
||||
}}
|
||||
>
|
||||
<Board
|
||||
<TicTacToeBoard
|
||||
board={board}
|
||||
turn={turn}
|
||||
winner={winner}
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import Leaderboard from "./Leaderboard";
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
|
||||
export default function Player({
|
||||
@@ -238,7 +237,6 @@ export default function Player({
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: "24px" }}>
|
||||
<Leaderboard />
|
||||
</div>
|
||||
|
||||
<motion.button
|
||||
@@ -1,14 +1,8 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
import getHaiku from "./utils/haikus";
|
||||
|
||||
export interface PlayerModel {
|
||||
user_id: string;
|
||||
username: string;
|
||||
index: number;
|
||||
metadata: Record<string, string>; // e.g. { symbol: "X" }
|
||||
}
|
||||
import { useNakama } from "../../providers/NakamaProvider";
|
||||
import getHaiku from "../../utils/haikus";
|
||||
import { PlayerModel } from "../../models/player";
|
||||
|
||||
interface BoardProps {
|
||||
board: string[][];
|
||||
@@ -20,7 +14,7 @@ interface BoardProps {
|
||||
onCellClick: (row: number, col: number) => void;
|
||||
}
|
||||
|
||||
export default function Board({
|
||||
export default function TicTacToeBoard({
|
||||
board,
|
||||
turn,
|
||||
winner,
|
||||
@@ -4,9 +4,9 @@ import {
|
||||
ApiLeaderboardRecordList,
|
||||
// @ts-ignore
|
||||
} from "@heroiclabs/nakama-js/dist/api.gen"
|
||||
import { useNakama } from "./providers/NakamaProvider";
|
||||
import { useNakama } from "../../providers/NakamaProvider";
|
||||
|
||||
export default function Leaderboard({
|
||||
export default function TicTacToeLeaderboard({
|
||||
intervalMs = 10000,
|
||||
}: {
|
||||
intervalMs?: number;
|
||||
@@ -1,14 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import TicTacToe from './tictactoe/TicTacToe';
|
||||
import { NakamaProvider } from './tictactoe/providers/NakamaProvider';
|
||||
import "./tictactoe/styles.css";
|
||||
import App from './App';
|
||||
import { NakamaProvider } from './providers/NakamaProvider';
|
||||
import "./styles.css";
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
const root = createRoot(rootElement);
|
||||
|
||||
root.render(
|
||||
<NakamaProvider>
|
||||
<TicTacToe />
|
||||
<App />
|
||||
</NakamaProvider>,
|
||||
);
|
||||
|
||||
6
src/models/player.ts
Normal file
6
src/models/player.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export interface PlayerModel {
|
||||
user_id: string;
|
||||
username: string;
|
||||
index: number;
|
||||
metadata: Record<string, string>; // e.g. { symbol: "X" }
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import { Match } from "@heroiclabs/nakama-js";
|
||||
|
||||
interface MatchListProps {
|
||||
matches: Match[];
|
||||
}
|
||||
|
||||
export default function MatchList({ matches }: MatchListProps) {
|
||||
if (!matches.length) return <p>No open matches</p>;
|
||||
|
||||
return (
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
<h3>Open Matches</h3>
|
||||
|
||||
<table
|
||||
style={{
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
marginTop: "10px",
|
||||
}}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={th}>Sr No.</th>
|
||||
<th style={th}>Match ID</th>
|
||||
<th style={th}>Label</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{matches
|
||||
.filter(m => m.size ?? 0 > 0)
|
||||
.map((m, index) => (
|
||||
<tr key={m.match_id}>
|
||||
<td style={td}>{index + 1}</td>
|
||||
<td style={td}>{m.match_id}</td>
|
||||
<td style={td}>{m.label ?? "-"}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const th: React.CSSProperties = {
|
||||
textAlign: "left",
|
||||
padding: "8px",
|
||||
background: "#f2f2f2",
|
||||
borderBottom: "1px solid #ccc",
|
||||
};
|
||||
|
||||
const td: React.CSSProperties = {
|
||||
padding: "8px",
|
||||
borderBottom: "1px solid #eee",
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
interface SquareProps {
|
||||
value: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export default function Square({ value, onClick } : SquareProps) {
|
||||
return (
|
||||
<button className="square" onClick={onClick}>
|
||||
{value}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user