Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default [
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react/prop-types': 'off',
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'prettier/prettier': 'error',
},
Expand Down
8 changes: 4 additions & 4 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
<script>
(function () {
try {
var t = localStorage.getItem('theme')
var t = localStorage.getItem('theme');
if (t === 'dark' || (!t && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark')
document.documentElement.classList.remove('dark');
}
} catch (e) {}
})()
})();
</script>
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"lint:fix": "eslint . --fix && prettier --write .",
"preview": "vite preview"
},
"dependencies": {
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Deck from "./Components/Deck";
import Home from "./pages/Home";
import Error from "./pages/Error";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Deck from './Components/Deck';
import Home from './pages/Home';
import Error from './pages/Error';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
Expand All @@ -14,4 +14,4 @@ function App() {
);
}

export default App;
export default App;
106 changes: 57 additions & 49 deletions frontend/src/Components/ClueInput.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ClueInput.jsx
import React, { useState,useEffect } from 'react';
import { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import socket from '../socket';
Expand All @@ -20,7 +20,10 @@
// read currentTurn from the Redux store so we can restrict Concealer input to the active team
const currentTurn = useSelector((state) => state.game?.currentTurn ?? 'red');

const numbers = Array.from({ length: 10 }, (_, i) => ({ value: `${i + 1}`, label: `${i + 1}` })).concat({ value: 'infinity', label: '∞' });
const numbers = Array.from({ length: 10 }, (_, i) => ({ value: `${i + 1}`, label: `${i + 1}` })).concat({
value: 'infinity',
label: '∞',
});

useEffect(() => {
// If this client is a Revealer and there's a persisted clue, show it after reload/join
Expand All @@ -42,7 +45,7 @@
console.log('📬 clueReceived:', clueData);
setClueWord(clueData.word);
setClueNumber(clueData.number);
setIsSubmitted(true);
setIsSubmitted(true);
setCardsRevealed(0); // Reset counter for new turn
};
socket.on('clueReceived', onClueReceived);
Expand All @@ -55,7 +58,7 @@
const normalizedTurn = String(currentTurn || '').toLowerCase();
const isRoleConcealer = normalizedRole.startsWith('conceal') || normalizedRole === 'spymaster';
if (isRoleConcealer && normalizedTeam && normalizedTeam === normalizedTurn) {
setIsSubmitted(false);
setIsSubmitted(false);
setClueWord('');
setClueNumber('1');
setCardsRevealed(0);
Expand All @@ -70,7 +73,7 @@
const normalizedTurn = String(currentTurn || '').toLowerCase();
const isRoleConcealer = normalizedRole.startsWith('conceal') || normalizedRole === 'spymaster';
if (isRoleConcealer && normalizedTeam && normalizedTeam === normalizedTurn) {
setIsSubmitted(false);
setIsSubmitted(false);
setClueWord('');
setClueNumber('1');
setCardsRevealed(0);
Expand All @@ -83,21 +86,21 @@
socket.off('requestClue', onRequestClue);
socket.off('turnSwitched', onTurnSwitched);
};
}, [joinedTitle, joinedTeam]);

Check warning on line 89 in frontend/src/Components/ClueInput.jsx

View workflow job for this annotation

GitHub Actions / build-frontend

React Hook useEffect has missing dependencies: 'clueWord', 'ui?.clueDisplayActive', and 'ui.lastClue'. Either include them or remove the dependency array

useEffect(() => {
const onCardRevealed = ({ cardsRevealedThisTurn }) => {
console.log('🎯 Card revealed, count:', cardsRevealedThisTurn);
setCardsRevealed(cardsRevealedThisTurn || 0);

// Check if we've reached the clue number limit
if (cardsRevealedThisTurn && clueNumber !== 'infinity' && cardsRevealedThisTurn >= parseInt(clueNumber)) {
console.log(`✅ Clue limit reached! ${cardsRevealedThisTurn} cards revealed, switching turn...`);
setIsSubmitted(false);
setIsSubmitted(false);
setClueWord('');
setClueNumber('1');
setCardsRevealed(0);

// Emit switchTurn event
socket.emit('switchTurn', { gameId });
}
Expand Down Expand Up @@ -128,60 +131,65 @@
const isRoleConcealer = normalizedRole.startsWith('conceal') || normalizedRole === 'spymaster';
const isConcealers = isRoleConcealer && normalizedTeam && normalizedTeam === normalizedTurn;

useEffect(()=>{
console.log("ClueWord:",clueWord);
},[])
useEffect(() => {
console.log('ClueWord:', clueWord);
}, []);

Check warning on line 136 in frontend/src/Components/ClueInput.jsx

View workflow job for this annotation

GitHub Actions / build-frontend

React Hook useEffect has a missing dependency: 'clueWord'. Either include it or remove the dependency array

return (
<div>
{!isSubmitted && isConcealers ? (
<div className="w-[1100px] mt-6 p-4 rounded-[30px] dark:bg-black/60 bg-white/70 shadow-2xl flex items-center justify-center border dark:border-white/10 border-gray-400 backdrop-blur-sm">
<form onSubmit={handleSubmit} className="flex items-center space-x-3 w-full justify-center">
<input
type="text"
value={clueWord}
onChange={(e) => setClueWord(e.target.value)}
placeholder="Enter one-word clue"
className="flex-grow p-3 rounded-xl border dark:border-gray-700 bg-input dark:bg-gray-800 text-foreground dark:text-white focus:ring-2 focus:ring-primary max-w-[400px]"
/>
<select
value={clueNumber}
onChange={(e) => setClueNumber(e.target.value)}
className="py-3 px-3 rounded-xl bg-sidebar-accent dark:bg-sidebar-accent text-sidebar-accent-foreground font-bold cursor-pointer"
>
{numbers.map((num) => (
<option key={num.value} value={num.value}>{num.label}</option>
))}
</select>
<button
type="submit"
className="h-12 w-12 flex items-center justify-center rounded-full bg-primary text-primary-foreground hover:bg-opacity-90 transition-opacity duration-300 shadow-md"
disabled={!clueWord.trim()}
title="Submit Clue"
>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" strokeWidth={3} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
</svg>
</button>
</form>
{!isSubmitted && isConcealers ? (
<div className="w-[1100px] mt-6 p-4 rounded-[30px] dark:bg-black/60 bg-white/70 shadow-2xl flex items-center justify-center border dark:border-white/10 border-gray-400 backdrop-blur-sm">
<form onSubmit={handleSubmit} className="flex items-center space-x-3 w-full justify-center">
<input
type="text"
value={clueWord}
onChange={(e) => setClueWord(e.target.value)}
placeholder="Enter one-word clue"
className="flex-grow p-3 rounded-xl border dark:border-gray-700 bg-input dark:bg-gray-800 text-foreground dark:text-white focus:ring-2 focus:ring-primary max-w-[400px]"
/>
<select
value={clueNumber}
onChange={(e) => setClueNumber(e.target.value)}
className="py-3 px-3 rounded-xl bg-sidebar-accent dark:bg-sidebar-accent text-sidebar-accent-foreground font-bold cursor-pointer"
>
{numbers.map((num) => (
<option key={num.value} value={num.value}>
{num.label}
</option>
))}
</select>
<button
type="submit"
className="h-12 w-12 flex items-center justify-center rounded-full bg-primary text-primary-foreground hover:bg-opacity-90 transition-opacity duration-300 shadow-md"
disabled={!clueWord.trim()}
title="Submit Clue"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
strokeWidth={3}
stroke="currentColor"
className="w-6 h-6"
>
<path strokeLinecap="round" strokeLinejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
</svg>
</button>
</form>
</div>
) : (
clueWord ? (
) : clueWord ? (
<div className="text-center">
<div className="text-2xl font-bold tracking-wide text-gray-900 dark:text-white mb-2">
<span className="uppercase">{clueWord}</span>{" "}
<span className="uppercase">{clueWord}</span>{' '}
<span className="text-primary font-extrabold">({clueNumber === 'infinity' ? '∞' : clueNumber})</span>
</div>
<div className="text-sm text-gray-600 dark:text-gray-300">
{cardsRevealed} / {clueNumber === 'infinity' ? '∞' : clueNumber} cards revealed
</div>
</div>

) : (
<></>
)
) : (
<></>
)}
</div>
</div>
);
};

Expand Down
Loading
Loading