-
{/* Custom Keyframes for floating words - Increased travel distance */}
-
+
{/* 1. Floating Words Background Layer (Now covers the whole screen) */}
{/* Opacity is set to 100% here, letting the individual word component handle transparency */}
-
- {wordElements}
-
+
{wordElements}
{/* Main Content Card */}
@@ -152,8 +148,7 @@ const Home = () => {
onClick={handleCreateGame}
disabled={isLoading || !nickname.trim() || (gameId && nickname)}
className={`w-full py-3 px-4 rounded-lg bg-primary text-primary-foreground font-semibold shadow-lg transition-opacity duration-200
- ${(isLoading || !nickname.trim() || (gameId && nickname)) ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}`
- }
+ ${isLoading || !nickname.trim() || (gameId && nickname) ? 'opacity-50 cursor-not-allowed' : 'hover:opacity-90'}`}
>
{isLoading ? 'Creating...' : 'Create New Game'}
@@ -163,11 +158,11 @@ const Home = () => {
onClick={handleJoinGame}
disabled={!gameId.trim() || !nickname.trim()}
className={`w-full py-3 px-4 rounded-lg font-semibold shadow-md transition-all duration-200
- ${(!gameId.trim() || !nickname.trim())
- ? 'bg-muted text-muted-foreground cursor-not-allowed opacity-70'
- : 'bg-secondary text-secondary-foreground hover:bg-secondary/80'
- }`
- }
+ ${
+ !gameId.trim() || !nickname.trim()
+ ? 'bg-muted text-muted-foreground cursor-not-allowed opacity-70'
+ : 'bg-secondary text-secondary-foreground hover:bg-secondary/80'
+ }`}
>
Join Existing Game
@@ -183,4 +178,4 @@ const Home = () => {
);
};
-export default Home;
\ No newline at end of file
+export default Home;
diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js
index 6c76b84..9cba45c 100644
--- a/frontend/src/store/index.js
+++ b/frontend/src/store/index.js
@@ -1,28 +1,19 @@
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from 'redux';
-import {
- persistStore,
- persistReducer,
- FLUSH,
- REHYDRATE,
- PAUSE,
- PERSIST,
- PURGE,
- REGISTER,
-} from 'redux-persist';
+import { persistStore, persistReducer, FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from 'redux-persist';
import storage from 'redux-persist/lib/storage'; // localStorage
import cardsReducer from './slices/cardsSlice';
import uiReducer from './slices/uiSlice';
-import scoreReducer from "./slices/scoreSlice";
-import playersReducer from "./slices/playersSlice";
-import gameReducer from "./slices/gameSlice";
+import scoreReducer from './slices/scoreSlice';
+import playersReducer from './slices/playersSlice';
+import gameReducer from './slices/gameSlice';
const rootReducer = combineReducers({
cards: cardsReducer,
ui: uiReducer,
scores: scoreReducer,
players: playersReducer,
- game: gameReducer
+ game: gameReducer,
});
const persistConfig = {
diff --git a/frontend/src/store/slices/cardsSlice.js b/frontend/src/store/slices/cardsSlice.js
index 7257eac..4cdab75 100644
--- a/frontend/src/store/slices/cardsSlice.js
+++ b/frontend/src/store/slices/cardsSlice.js
@@ -4,38 +4,38 @@ import socket from '../../socket';
// initial cards (same as your deck)
const initialCardsList = [
- { word: "Phoenix", team: "blue" },
- { word: "Dragon", team: "red" },
- { word: "Ocean", team: "blue" },
- { word: "Flame", team: "red" },
- { word: "Crystal", team: "blue" },
- { word: "Sunset", team: "red" },
- { word: "Arctic", team: "blue" },
- { word: "Mars", team: "red" },
- { word: "Neptune", team: "blue" },
- { word: "Volcano", team: "red" },
- { word: "Glacier", team: "blue" },
- { word: "Torch", team: "red" },
- { word: "Sapphire", team: "blue" },
- { word: "Ruby", team: "red" },
- { word: "River", team: "blue" },
- { word: "Ember", team: "red" },
- { word: "Frost", team: "blue" },
- { word: "Castle", team: "neutral" },
- { word: "Tower", team: "neutral" },
- { word: "Bridge", team: "neutral" },
- { word: "Garden", team: "neutral" },
- { word: "Pyramid", team: "neutral" },
- { word: "Temple", team: "neutral" },
- { word: "Mountain", team: "neutral" },
- { word: "Assassin", team: "assassin" },
+ { word: 'Phoenix', team: 'blue' },
+ { word: 'Dragon', team: 'red' },
+ { word: 'Ocean', team: 'blue' },
+ { word: 'Flame', team: 'red' },
+ { word: 'Crystal', team: 'blue' },
+ { word: 'Sunset', team: 'red' },
+ { word: 'Arctic', team: 'blue' },
+ { word: 'Mars', team: 'red' },
+ { word: 'Neptune', team: 'blue' },
+ { word: 'Volcano', team: 'red' },
+ { word: 'Glacier', team: 'blue' },
+ { word: 'Torch', team: 'red' },
+ { word: 'Sapphire', team: 'blue' },
+ { word: 'Ruby', team: 'red' },
+ { word: 'River', team: 'blue' },
+ { word: 'Ember', team: 'red' },
+ { word: 'Frost', team: 'blue' },
+ { word: 'Castle', team: 'neutral' },
+ { word: 'Tower', team: 'neutral' },
+ { word: 'Bridge', team: 'neutral' },
+ { word: 'Garden', team: 'neutral' },
+ { word: 'Pyramid', team: 'neutral' },
+ { word: 'Temple', team: 'neutral' },
+ { word: 'Mountain', team: 'neutral' },
+ { word: 'Assassin', team: 'assassin' },
];
const initialState = {
cards: initialCardsList.map((c, i) => ({
...c,
id: i,
- revealed: false, // fully revealed (shows team color)
+ revealed: false, // fully revealed (shows team color)
pendingReveal: false, // animation in progress
})),
status: 'idle',
@@ -91,7 +91,7 @@ const cardsSlice = createSlice({
id: i,
revealed: c.revealed ?? false,
pendingReveal: false,
- clickedBy: c.clickedBy ?? []
+ clickedBy: c.clickedBy ?? [],
}));
},
updateCardClickedBy(state, action) {
diff --git a/frontend/src/store/slices/gameSlice.js b/frontend/src/store/slices/gameSlice.js
index af93222..78fc7fe 100644
--- a/frontend/src/store/slices/gameSlice.js
+++ b/frontend/src/store/slices/gameSlice.js
@@ -1,15 +1,15 @@
-import { createSlice } from "@reduxjs/toolkit";
+import { createSlice } from '@reduxjs/toolkit';
const gameSlice = createSlice({
- name: "game",
+ name: 'game',
initialState: {
- currentTurn: "red" // "red" or "blue"
+ currentTurn: 'red', // "red" or "blue"
},
reducers: {
setCurrentTurn(state, action) {
state.currentTurn = action.payload;
- }
- }
+ },
+ },
});
export const { setCurrentTurn } = gameSlice.actions;
diff --git a/frontend/src/store/slices/playersSlice.js b/frontend/src/store/slices/playersSlice.js
index e3e1264..48ee17c 100644
--- a/frontend/src/store/slices/playersSlice.js
+++ b/frontend/src/store/slices/playersSlice.js
@@ -1,16 +1,16 @@
-import { createSlice } from "@reduxjs/toolkit";
+import { createSlice } from '@reduxjs/toolkit';
const playersSlice = createSlice({
- name: "players",
+ name: 'players',
initialState: {
- list: [] // Array of { socketId, name, team, role, _id }
+ list: [], // Array of { socketId, name, team, role, _id }
},
reducers: {
updatePlayers(state, action) {
// action.payload should be { players: [...] } from server
state.list = action.payload.players || [];
- }
- }
+ },
+ },
});
export const { updatePlayers } = playersSlice.actions;
diff --git a/frontend/src/store/slices/scoreSlice.js b/frontend/src/store/slices/scoreSlice.js
index bbbf732..fd936c5 100644
--- a/frontend/src/store/slices/scoreSlice.js
+++ b/frontend/src/store/slices/scoreSlice.js
@@ -1,7 +1,7 @@
-import { createSlice } from "@reduxjs/toolkit";
+import { createSlice } from '@reduxjs/toolkit';
const scoreSlice = createSlice({
- name: "scores",
+ name: 'scores',
initialState: { red: 9, blue: 8 },
reducers: {
updateScores(state, action) {
@@ -13,8 +13,8 @@ const scoreSlice = createSlice({
state.red = action.payload.redScore;
state.blue = action.payload.blueScore;
}
- }
- }
+ },
+ },
});
export const { updateScores } = scoreSlice.actions;
diff --git a/frontend/src/store/slices/uiSlice.js b/frontend/src/store/slices/uiSlice.js
index 52be344..6bddab6 100644
--- a/frontend/src/store/slices/uiSlice.js
+++ b/frontend/src/store/slices/uiSlice.js
@@ -46,9 +46,16 @@ const uiSlice = createSlice({
// Clear all selections
clearConfirmTargets: (state) => {
state.confirmTargetIds = [];
- }
+ },
},
});
-export const { showOverlay, hideOverlay, showClueDisplay, hideClueDisplay, toggleConfirmTarget, removeConfirmTarget, clearConfirmTargets } = uiSlice.actions;
+export const {
+ showOverlay,
+ hideOverlay,
+ showClueDisplay,
+ hideClueDisplay,
+ toggleConfirmTarget,
+ removeConfirmTarget,
+ clearConfirmTargets,
+} = uiSlice.actions;
export default uiSlice.reducer;
-
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js
index faf612d..2701895 100644
--- a/frontend/tailwind.config.js
+++ b/frontend/tailwind.config.js
@@ -3,10 +3,7 @@
/** @type {import('tailwindcss').Config} */
export default {
// 1. Tell Tailwind where to find your files to scan for classes
- content: [
- "./index.html",
- "./src/**/*.{js,ts,jsx,tsx}",
- ],
+ content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
backgroundSize: {
@@ -14,25 +11,25 @@ export default {
},
},
},
-
+
// 2. Safelist the dynamic classes to fix the issue
safelist: [
// Shadow classes
'shadow-blue-500/40',
'shadow-red-500/40',
-
+
// Gradient from classes
'from-blue-500',
'from-red-500',
-
+
// Gradient via classes
'via-blue-600',
'via-red-600',
-
+
// Gradient to classes
'to-blue-700',
'to-red-700',
-
+
// Border classes
'border-blue-400/30',
'border-red-400/30',
@@ -44,6 +41,6 @@ export default {
'card-back',
'flipped',
],
-
+
plugins: [],
-}
\ No newline at end of file
+};
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
index 3d15f68..6e7f528 100644
--- a/frontend/vite.config.js
+++ b/frontend/vite.config.js
@@ -1,11 +1,8 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
-import tailwindcss from '@tailwindcss/vite'
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import tailwindcss from '@tailwindcss/vite';
// https://vite.dev/config/
export default defineConfig({
- plugins: [
- react(),
- tailwindcss(),
- ],
-})
+ plugins: [react(), tailwindcss()],
+});