- {import.meta.env.DEV &&
}
-
-
-
-
-
-
-
-
-
-
-
+
+ {import.meta.env.DEV &&
}
+
+
-
+
+
+
+
+
+
+
+
diff --git a/src/routes/index/components/openGame/OpenGame.tsx b/src/routes/index/components/openGame/OpenGame.tsx
index 8c737c14c..3b5302b24 100644
--- a/src/routes/index/components/openGame/OpenGame.tsx
+++ b/src/routes/index/components/openGame/OpenGame.tsx
@@ -1,11 +1,9 @@
-import React, { useContext } from 'react';
import classNames from 'classnames';
import { useNavigate } from 'react-router-dom';
import { IOpenGame } from '../gameList/GameList';
import styles from './OpenGame.module.css';
import { generateCroppedImageUrl } from '../../../../utils/cropImages';
import FriendBadge from '../gameList/FriendBadge';
-import QuickJoinContext from '../quickJoin/QuickJoinContext';
const OpenGame = ({
ix,
@@ -19,27 +17,16 @@ const OpenGame = ({
isFriendsGame?: boolean;
}) => {
const navigate = useNavigate();
- const quickJoinCtx = useContext(QuickJoinContext);
-
- const hasDeckReady = !!(quickJoinCtx?.hasDeckConfigured);
-
- const handleJoin = (e: React.MouseEvent) => {
- e.preventDefault();
- e.stopPropagation();
- if (hasDeckReady && quickJoinCtx) {
- quickJoinCtx.quickJoin(entry.gameName);
- } else {
- navigate(`/game/join/${entry.gameName}`);
- }
- };
-
const buttonClass = classNames(styles.button, 'secondary');
return (
{
+ e.preventDefault();
+ navigate(`/game/join/${entry.gameName}`);
+ }}
>
{!!entry.p1Hero ? (
@@ -56,8 +43,10 @@ const OpenGame = ({
className={buttonClass}
href={`/game/join/${entry.gameName}`}
role="button"
- onClick={handleJoin}
- title={hasDeckReady ? 'Join using your pre-configured deck' : 'Select a deck to join'}
+ onClick={(e) => {
+ e.preventDefault();
+ navigate(`/game/join/${entry.gameName}`);
+ }}
>
Join
diff --git a/src/routes/index/components/quickJoin/QuickJoinContext.tsx b/src/routes/index/components/quickJoin/QuickJoinContext.tsx
deleted file mode 100644
index 3fd2250bb..000000000
--- a/src/routes/index/components/quickJoin/QuickJoinContext.tsx
+++ /dev/null
@@ -1,185 +0,0 @@
-import React, {
- createContext,
- useCallback,
- useContext,
- useEffect,
- useMemo,
- useState
-} from 'react';
-import { useNavigate } from 'react-router-dom';
-import { useAppDispatch } from 'app/Hooks';
-import { setGameStart } from 'features/game/GameSlice';
-import { useJoinGameMutation, useGetFavoriteDecksQuery } from 'features/api/apiSlice';
-import { generateCroppedImageUrl } from 'utils/cropImages';
-import { ImageSelectOption } from 'components/ImageSelect';
-import { getReadableFormatName } from 'utils/formatUtils';
-
-const shortenFormat = (format: string): string => {
- if (!format) return '';
- if (format.toLowerCase() === 'classic constructed') return 'CC';
- const readable = getReadableFormatName(format);
- return readable || format;
-};
-
-interface QuickJoinContextType {
- selectedFavoriteDeck: string;
- importDeckUrl: string;
- saveDeck: boolean;
- detectedFormat: string | null;
- error: string | null;
- isJoining: boolean;
- hasDeckConfigured: boolean;
- favoriteDeckOptions: ImageSelectOption[];
- isFavoritesLoading: boolean;
- setSelectedFavoriteDeck: (v: string) => void;
- setImportDeckUrl: (v: string) => void;
- setSaveDeck: (v: boolean) => void;
- setError: (v: string | null) => void;
- quickJoin: (gameName: number) => Promise
;
-}
-
-const QuickJoinContext = createContext(null);
-
-const LS_FAVE_DECK_KEY = 'quickJoin_favoriteDeck';
-const LS_IMPORT_URL_KEY = 'quickJoin_importUrl';
-const LS_SAVE_DECK_KEY = 'quickJoin_saveDeck';
-
-export const QuickJoinProvider = ({ children }: { children: React.ReactNode }) => {
- const navigate = useNavigate();
- const dispatch = useAppDispatch();
- const [joinGame] = useJoinGameMutation();
- const { data: favoritesData, isLoading: isFavoritesLoading } = useGetFavoriteDecksQuery(undefined);
-
- const [selectedFavoriteDeck, setSelectedFavoriteDeckState] = useState(
- () => localStorage.getItem(LS_FAVE_DECK_KEY) ?? ''
- );
- const [importDeckUrl, setImportDeckUrlState] = useState(
- () => localStorage.getItem(LS_IMPORT_URL_KEY) ?? ''
- );
- const [saveDeck, setSaveDeckState] = useState(
- () => localStorage.getItem(LS_SAVE_DECK_KEY) === 'true'
- );
- const [detectedFormat, setDetectedFormat] = useState(null);
- const [error, setError] = useState(null);
- const [isJoining, setIsJoining] = useState(false);
-
- const favoriteDeckOptions: ImageSelectOption[] = useMemo(() => {
- if (!favoritesData?.favoriteDecks) return [];
- return favoritesData.favoriteDecks.map((deck) => ({
- value: deck.key,
- label: `${deck.name}${deck.format ? ` (${shortenFormat(deck.format)})` : ''}`,
- imageUrl: generateCroppedImageUrl(deck.hero)
- }));
- }, [favoritesData?.favoriteDecks]);
-
- useEffect(() => {
- if (!selectedFavoriteDeck || !favoritesData?.favoriteDecks) {
- if (!importDeckUrl) setDetectedFormat(null);
- return;
- }
- const found = favoritesData.favoriteDecks.find(
- (deck) => deck.key === selectedFavoriteDeck
- );
- if (found?.format) {
- setDetectedFormat(getReadableFormatName(found.format));
- } else {
- setDetectedFormat(null);
- }
- }, [selectedFavoriteDeck, favoritesData?.favoriteDecks, importDeckUrl]);
-
- const setSelectedFavoriteDeck = useCallback((v: string) => {
- setSelectedFavoriteDeckState(v);
- localStorage.setItem(LS_FAVE_DECK_KEY, v);
- if (v) {
- setImportDeckUrlState('');
- localStorage.setItem(LS_IMPORT_URL_KEY, '');
- }
- setError(null);
- }, []);
-
- const setImportDeckUrl = useCallback((v: string) => {
- setImportDeckUrlState(v);
- localStorage.setItem(LS_IMPORT_URL_KEY, v);
- if (v) {
- setSelectedFavoriteDeckState('');
- localStorage.setItem(LS_FAVE_DECK_KEY, '');
- setDetectedFormat(null);
- }
- setError(null);
- }, []);
-
- const setSaveDeck = useCallback((v: boolean) => {
- setSaveDeckState(v);
- localStorage.setItem(LS_SAVE_DECK_KEY, String(v));
- }, []);
-
- const hasDeckConfigured = !!(selectedFavoriteDeck || importDeckUrl.trim());
-
- const quickJoin = useCallback(
- async (gameName: number) => {
- setError(null);
- setIsJoining(true);
- try {
- const response = await joinGame({
- gameName,
- playerID: 2,
- favoriteDecks: selectedFavoriteDeck || undefined,
- fabdb: importDeckUrl.trim() || undefined,
- favoriteDeck: saveDeck
- }).unwrap();
-
- if (response.error) {
- throw response.error;
- }
-
- dispatch(
- setGameStart({
- playerID: response.playerID ?? 0,
- gameID: response.gameName ?? 0,
- authKey: response.authKey ?? ''
- })
- );
- navigate(`/game/lobby/${response.gameName}`, {
- state: { playerID: response.playerID ?? 0 }
- });
- } catch (err: any) {
- const message = typeof err === 'string' ? err : err?.message ?? String(err);
- setError(message);
- } finally {
- setIsJoining(false);
- }
- },
- [joinGame, selectedFavoriteDeck, importDeckUrl, saveDeck, dispatch, navigate]
- );
-
- const value: QuickJoinContextType = {
- selectedFavoriteDeck,
- importDeckUrl,
- saveDeck,
- detectedFormat,
- error,
- isJoining,
- hasDeckConfigured,
- favoriteDeckOptions,
- isFavoritesLoading,
- setSelectedFavoriteDeck,
- setImportDeckUrl,
- setSaveDeck,
- setError,
- quickJoin
- };
-
- return (
-
- {children}
-
- );
-};
-
-export const useQuickJoin = (): QuickJoinContextType => {
- const ctx = useContext(QuickJoinContext);
- if (!ctx) throw new Error('useQuickJoin must be used inside ');
- return ctx;
-};
-
-export default QuickJoinContext;
diff --git a/src/routes/index/components/quickJoin/QuickJoinPanel.module.css b/src/routes/index/components/quickJoin/QuickJoinPanel.module.css
deleted file mode 100644
index b84c2ee96..000000000
--- a/src/routes/index/components/quickJoin/QuickJoinPanel.module.css
+++ /dev/null
@@ -1,85 +0,0 @@
-.panel {
- max-width: 900px;
- border: 1px solid var(--theme-border, rgba(255, 255, 255, 0.2));
- border-radius: 10px;
- margin: 1.5em auto;
- margin-bottom: 0;
- padding: 1.25rem 1.5rem 1rem;
- background: var(--theme-section-background, linear-gradient(135deg, rgba(30, 35, 41, 0.8) 0%, rgba(30, 35, 41, 0.85) 100%));
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-.title {
- margin: 0 0 0.25rem;
- font-size: 1.1rem;
- font-weight: 700;
- color: var(--theme-text, #ededed);
-}
-
-.label {
- display: flex;
- flex-direction: column;
- gap: 0.3rem;
- font-size: var(--font-size);
- color: var(--theme-text, #ededed);
-}
-
-.labelText {
- display: flex;
- align-items: center;
- gap: 4px;
-}
-
-.textInput {
- width: 100%;
- box-sizing: border-box;
- margin-bottom: 0 !important;
-}
-
-.toggleLabel {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: var(--font-size);
- cursor: pointer;
- margin: 0;
-}
-
-/* Error box mirrors the look of existing fieldError patterns */
-.errorBox {
- display: flex;
- align-items: flex-start;
- gap: 0.4rem;
- color: var(--alarm, red);
- font-size: 0.875rem;
- background: rgba(200, 0, 0, 0.08);
- border: 1px solid rgba(200, 0, 0, 0.25);
- border-radius: 6px;
- padding: 0.5rem 0.75rem;
-}
-
-.errorIcon {
- flex-shrink: 0;
- margin-top: 2px;
-}
-
-.joiningText {
- font-size: 0.875rem;
- color: var(--theme-primary, #d4af37);
- margin: 0;
- text-align: center;
-}
-
-.hint {
- font-size: 0.8rem;
- margin: 0;
-}
-
-@media (max-width: 768px) {
- .panel {
- border-radius: 10px;
- margin: 1em 0;
- }
-}
diff --git a/src/routes/index/components/quickJoin/QuickJoinPanel.tsx b/src/routes/index/components/quickJoin/QuickJoinPanel.tsx
deleted file mode 100644
index fb3926161..000000000
--- a/src/routes/index/components/quickJoin/QuickJoinPanel.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import React from 'react';
-import { FaExclamationCircle, FaQuestionCircle } from 'react-icons/fa';
-import { ImageSelect } from 'components/ImageSelect';
-import useAuth from 'hooks/useAuth';
-import { useQuickJoin } from './QuickJoinContext';
-import styles from './QuickJoinPanel.module.css';
-
-const QuickJoinPanel = () => {
- const { isLoggedIn } = useAuth();
- const {
- selectedFavoriteDeck,
- importDeckUrl,
- saveDeck,
- detectedFormat,
- error,
- isJoining,
- favoriteDeckOptions,
- isFavoritesLoading,
- setSelectedFavoriteDeck,
- setImportDeckUrl,
- setSaveDeck,
- setError
- } = useQuickJoin();
-
- if (!isLoggedIn) return null;
-
- return (
-
- );
-};
-
-export default QuickJoinPanel;
diff --git a/src/routes/index/components/quickJoin/index.ts b/src/routes/index/components/quickJoin/index.ts
deleted file mode 100644
index 5aff5c82d..000000000
--- a/src/routes/index/components/quickJoin/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { QuickJoinProvider, useQuickJoin } from './QuickJoinContext';
-export { default as QuickJoinPanel } from './QuickJoinPanel';