diff --git a/components/DeckBuilderCardBrowser.js b/components/DeckBuilderCardBrowser.js new file mode 100644 index 0000000..ee4088b --- /dev/null +++ b/components/DeckBuilderCardBrowser.js @@ -0,0 +1,761 @@ +/* eslint-disable @next/next/no-img-element -- External card image URLs; next/image migration is out of scope. */ +import { ManaCost, ColorFilterSymbol } from './ManaSymbols'; +import ManaSymbolSettings from './ManaSymbolSettings'; + +export default function DeckBuilderCardBrowser({ + selectedCard, + onSelectCard, + onClearSelectedCard, + viewMode, + onViewModeChange, + showSettings, + onToggleSettings, + onCollapseSidebar, + searchQuery, + onSearchQueryChange, + showFilters, + onToggleFilters, + filters, + onFiltersChange, + onClearFilters, + onToggleColorFilter, + searchLoading, + searchResults, + manaSymbolSettings, + onManaSymbolSettingsChange, + onAddCardToDeck, +}) { + return ( +
+ + {!selectedCard ? ( + + <> + + {/* Header */} + +
+ +

Card Browser

+ +
+ + {/* View Mode Toggle */} + +
+ + + + + +
+ + + + + +
+ +
+ + + + {/* Search */} + +
+ +
+ + onSearchQueryChange(e.target.value)} + + placeholder="Search for cards..." + + className="flex-1 px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-primary text-text-primary text-sm" + + /> + + + +
+ +
+ + + + {/* Settings Panel */} + + {showSettings && ( + +
+ + + +
+ + )} + + + + {/* Quick Filters */} + + {showFilters && ( + +
+ + {/* Color Filters */} + +
+ +
+ + + + {(filters.colors.length > 0 || filters.cmc || filters.rarity) && ( + + + + )} + +
+ +
+ + {['W', 'U', 'B', 'R', 'G'].map(color => ( + + + + ))} + +
+ +
+ + + + {/* CMC and Rarity */} + +
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+ +
+ + )} + + + + {/* Card List */} + +
+ + {viewMode === 'list' ? ( + + /* List View */ + +
+ + {searchLoading ? ( + +
+ +
+ +

Searching...

+ +
+ + ) : searchResults.length === 0 ? ( + +
+ +
🔍
+ +

+ + {searchQuery ? 'No cards found' : 'No cards available'} + +

+ +
+ + ) : ( + + searchResults.map((card) => ( + +
onSelectCard(card)} + + > + +
+ + {card.image_url && ( + + {card.name} + + )} + +
+ +

{card.name}

+ +

{card.set_name}

+ +
+ + {card.mana_cost && ( + + + + )} + + {card.rarity && ( + + + + {card.rarity[0].toUpperCase()} + + + + )} + +
+ +
+ +
+ +
+ + )) + + )} + +
+ + ) : ( + + /* Thumbnail View */ + +
+ + {searchLoading ? ( + +
+ +
+ +

Searching...

+ +
+ + ) : searchResults.length === 0 ? ( + +
+ +
🔍
+ +

+ + {searchQuery ? 'No cards found' : 'No cards available'} + +

+ +
+ + ) : ( + +
+ + {searchResults.map((card) => ( + +
onSelectCard(card)} + + > + + {card.image_url ? ( + +
+ + {card.name} + + {/* Hover overlay with card name */} + +
+ +
+ +

{card.name}

+ +

{card.set_name}

+ +
+ +
+ + {/* Rarity indicator */} + + {card.rarity && ( + +
+ + )} + +
+ + ) : ( + +
+ +
+ +

{card.name}

+ +

{card.set_name}

+ +
+ +
+ + )} + +
+ + ))} + +
+ + )} + +
+ + )} + +
+ + + + ) : ( + + /* Card Detail View */ + + <> + + {/* Detail Header */} + +
+ + + +

{selectedCard.name}

+ +
+ + + + {/* Card Detail Content */} + +
+ +
+ + {/* Card Image */} + + {selectedCard.image_url && ( + +
+ + {selectedCard.name} + +
+ + )} + + + + {/* Card Info */} + +
+ +
+ +

{selectedCard.name}

+ +

{selectedCard.set_name}

+ +
+ + + + {selectedCard.mana_cost && ( + +
+ + + +
+ + + +
+ +
+ + )} + + + + {selectedCard.card_type && ( + +
+ + + +
{selectedCard.card_type}
+ +
+ + )} + + + + {selectedCard.oracle_text && ( + +
+ + + +
{selectedCard.oracle_text}
+ +
+ + )} + + + +
+ + {selectedCard.rarity && ( + +
+ + + +
+ + {selectedCard.rarity} + +
+ +
+ + )} + + + + {selectedCard.cmc !== undefined && ( + +
+ + + +
{selectedCard.cmc}
+ +
+ + )} + +
+ +
+ +
+ +
+ + + + )} + + + + {/* Floating Action Button */} + + {selectedCard && ( + +
+ + + +
+ + )} + +
+ ); +} diff --git a/components/DeckBuilderDeckList.js b/components/DeckBuilderDeckList.js new file mode 100644 index 0000000..4b948e0 --- /dev/null +++ b/components/DeckBuilderDeckList.js @@ -0,0 +1,85 @@ +/* eslint-disable @next/next/no-img-element -- External card image URLs; next/image migration is out of scope. */ +import { ManaCost } from './ManaSymbols'; + +export default function DeckBuilderDeckList({ + deckCards, + sidebarOpen, + onOpenSidebar, + manaSymbolSettings, + onAddCard, + onRemoveCard, +}) { + return ( +
+ {deckCards.length === 0 ? ( +
+
🃏
+

Empty Deck

+

Start building your deck by searching for cards

+ {!sidebarOpen && ( + + )} +
+ ) : ( + deckCards + .sort((a, b) => a.name.localeCompare(b.name)) + .map((card) => ( +
+
+ {card.image_url && ( + {card.name} + )} +
+

{card.name}

+

{card.set_name}

+
+ {card.mana_cost && ( +
+ +
+ )} + {card.rarity && ( + + {card.rarity} + + )} +
+
+
+
+ {card.quantity}x +
+ + +
+
+
+ )) + )} +
+ ); +} diff --git a/pages/deck-builder.js b/pages/deck-builder.js index 70daf63..21b30b6 100644 --- a/pages/deck-builder.js +++ b/pages/deck-builder.js @@ -3,12 +3,11 @@ import { useState, useEffect, useRef } from 'react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import Layout from '../components/Layout'; +import DeckBuilderCardBrowser from '../components/DeckBuilderCardBrowser'; +import DeckBuilderDeckList from '../components/DeckBuilderDeckList'; import DeckBuilderStatsBar from '../components/DeckBuilderStatsBar'; -import { ManaCost, ColorIdentity, ColorFilterSymbol } from '../components/ManaSymbols'; -import ManaSymbolSettings from '../components/ManaSymbolSettings'; import { useAuth } from '../lib/use-auth'; import { computeDeckStats, isBasicLand } from '../lib/deck-builder-stats'; -import { getColorIdentity, getColorSymbol } from '../lib/mana-symbols'; export default function DeckBuilder() { const { user } = useAuth(); @@ -317,452 +316,45 @@ export default function DeckBuilder() { - {/* Deck Cards List */} -
- {deckCards.length === 0 ? ( -
-
🃏
-

Empty Deck

-

Start building your deck by searching for cards

- {!sidebarOpen && ( - - )} -
- ) : ( - deckCards - .sort((a, b) => a.name.localeCompare(b.name)) - .map((card) => ( -
-
- {card.image_url && ( - {card.name} - )} -
-

{card.name}

-

{card.set_name}

-
- {card.mana_cost && ( -
- -
- )} - {card.rarity && ( - - {card.rarity} - - )} -
-
-
-
- {card.quantity}x -
- - -
-
-
- )) - )} -
+ setSidebarOpen(true)} + manaSymbolSettings={manaSymbolSettings} + onAddCard={(card, quantity) => addCardToDeck(card, quantity)} + onRemoveCard={(cardId, quantity) => removeCardFromDeck(cardId, quantity)} + /> {/* Full Height Right Sidebar - Card Browser */}
-
- {!selectedCard ? ( - <> - {/* Header */} -
-

Card Browser

-
- {/* View Mode Toggle */} -
- - -
- - -
-
- - {/* Search */} -
-
- setSearchQuery(e.target.value)} - placeholder="Search for cards..." - className="flex-1 px-3 py-2 border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent-ember bg-bg-primary text-text-primary text-sm" - /> - -
-
- - {/* Settings Panel */} - {showSettings && ( -
- -
- )} - - {/* Quick Filters */} - {showFilters && ( -
- {/* Color Filters */} -
-
- - {(filters.colors.length > 0 || filters.cmc || filters.rarity) && ( - - )} -
-
- {['W', 'U', 'B', 'R', 'G'].map(color => ( - - ))} -
-
- - {/* CMC and Rarity */} -
-
- - -
-
- - -
-
-
- )} - - {/* Card List */} -
- {viewMode === 'list' ? ( - /* List View */ -
- {searchLoading ? ( -
-
-

Searching...

-
- ) : searchResults.length === 0 ? ( -
-
🔍
-

- {searchQuery ? 'No cards found' : 'No cards available'} -

-
- ) : ( - searchResults.map((card) => ( -
setSelectedCard(card)} - > -
- {card.image_url && ( - {card.name} - )} -
-

{card.name}

-

{card.set_name}

-
- {card.mana_cost && ( - - )} - {card.rarity && ( - - {card.rarity[0].toUpperCase()} - - )} -
-
-
-
- )) - )} -
- ) : ( - /* Thumbnail View */ -
- {searchLoading ? ( -
-
-

Searching...

-
- ) : searchResults.length === 0 ? ( -
-
🔍
-

- {searchQuery ? 'No cards found' : 'No cards available'} -

-
- ) : ( -
- {searchResults.map((card) => ( -
setSelectedCard(card)} - > - {card.image_url ? ( -
- {card.name} - {/* Hover overlay with card name */} -
-
-

{card.name}

-

{card.set_name}

-
-
- {/* Rarity indicator */} - {card.rarity && ( -
- )} -
- ) : ( -
-
-

{card.name}

-

{card.set_name}

-
-
- )} -
- ))} -
- )} -
- )} -
- - ) : ( - /* Card Detail View */ - <> - {/* Detail Header */} -
- -

{selectedCard.name}

-
- - {/* Card Detail Content */} -
-
- {/* Card Image */} - {selectedCard.image_url && ( -
- {selectedCard.name} -
- )} - - {/* Card Info */} -
-
-

{selectedCard.name}

-

{selectedCard.set_name}

-
- - {selectedCard.mana_cost && ( -
- -
- -
-
- )} - - {selectedCard.card_type && ( -
- -
{selectedCard.card_type}
-
- )} - - {selectedCard.oracle_text && ( -
- -
{selectedCard.oracle_text}
-
- )} - -
- {selectedCard.rarity && ( -
- -
- {selectedCard.rarity} -
-
- )} - - {selectedCard.cmc !== undefined && ( -
- -
{selectedCard.cmc}
-
- )} -
-
-
-
- - )} - - {/* Floating Action Button */} - {selectedCard && ( -
- -
- )} -
+ setSelectedCard(null)} + viewMode={viewMode} + onViewModeChange={setViewMode} + showSettings={showSettings} + onToggleSettings={() => setShowSettings(!showSettings)} + onCollapseSidebar={() => setSidebarOpen(false)} + searchQuery={searchQuery} + onSearchQueryChange={setSearchQuery} + showFilters={showFilters} + onToggleFilters={() => setShowFilters(!showFilters)} + filters={filters} + onFiltersChange={setFilters} + onClearFilters={clearFilters} + onToggleColorFilter={toggleColorFilter} + searchLoading={searchLoading} + searchResults={searchResults} + manaSymbolSettings={manaSymbolSettings} + onManaSymbolSettingsChange={setManaSymbolSettings} + onAddCardToDeck={(card) => { + addCardToDeck(card); + setSelectedCard(null); + }} + />