Fix CardDatabaseBrowser issues - prevent drawer closing, add event handling, and improve debugging
This commit is contained in:
parent
d9e7d856f0
commit
0c65919b02
2 changed files with 100 additions and 11 deletions
|
|
@ -41,23 +41,36 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
setIsSearching(true);
|
||||
try {
|
||||
const cards = await cardDataService.searchCards(debouncedSearch, selectedGame || undefined);
|
||||
console.log(`Found ${cards.length} cards for search "${debouncedSearch}" in game "${selectedGame}"`);
|
||||
return cards;
|
||||
} catch (error) {
|
||||
console.error('Error searching external cards:', error);
|
||||
return [];
|
||||
} finally {
|
||||
setIsSearching(false);
|
||||
}
|
||||
},
|
||||
enabled: !!debouncedSearch.trim() && isOpen,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
// Get random cards for discovery
|
||||
const { data: randomCards = [] } = useQuery({
|
||||
queryKey: ['random-cards', selectedGame],
|
||||
queryFn: async () => {
|
||||
return await cardDataService.getRandomCards(12, selectedGame || undefined);
|
||||
try {
|
||||
const cards = await cardDataService.getRandomCards(20, selectedGame || undefined);
|
||||
console.log(`Found ${cards.length} random cards for game "${selectedGame}"`);
|
||||
return cards;
|
||||
} catch (error) {
|
||||
console.error('Error fetching random cards:', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
enabled: isOpen && !debouncedSearch.trim(),
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
// Add card to database mutation
|
||||
|
|
@ -142,10 +155,25 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
const displayCards = debouncedSearch.trim() ? externalCards : randomCards;
|
||||
const isLoading = isSearchingExternal || isSearching;
|
||||
|
||||
// Debug logging
|
||||
console.log('CardDatabaseBrowser state:', {
|
||||
isOpen,
|
||||
searchTerm,
|
||||
debouncedSearch,
|
||||
selectedGame,
|
||||
externalCards: externalCards.length,
|
||||
randomCards: randomCards.length,
|
||||
displayCards: displayCards.length,
|
||||
isLoading
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="fixed inset-0 z-50 bg-black/50" onClick={onClose}>
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-white dark:bg-surface-900 rounded-t-3xl h-[90vh] overflow-hidden animate-slide-up">
|
||||
<div
|
||||
className="fixed bottom-0 left-0 right-0 bg-white dark:bg-surface-900 rounded-t-3xl h-[90vh] overflow-hidden animate-slide-up"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="p-4 pb-0">
|
||||
<div className="w-12 h-1.5 bg-surface-300 dark:bg-surface-600 rounded-full mx-auto mb-4"></div>
|
||||
|
||||
|
|
@ -155,7 +183,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
Card Database Browser
|
||||
</h2>
|
||||
<button
|
||||
onClick={onClose}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onClose();
|
||||
}}
|
||||
className="p-2 rounded-xl text-surface-400 hover:text-surface-600 dark:hover:text-surface-300 transition-colors"
|
||||
>
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
|
@ -175,6 +208,8 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
type="text"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
placeholder="Search cards from external databases..."
|
||||
className="w-full pl-10 pr-4 py-3 bg-surface-50 dark:bg-surface-700 border border-surface-300 dark:border-surface-600 rounded-xl text-surface-900 dark:text-white placeholder-surface-500 dark:placeholder-surface-400 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors"
|
||||
/>
|
||||
|
|
@ -183,7 +218,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
{/* Game Filter */}
|
||||
<div className="flex space-x-2 mb-4 overflow-x-auto pb-2">
|
||||
<button
|
||||
onClick={() => setSelectedGame('')}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setSelectedGame('');
|
||||
}}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
!selectedGame
|
||||
? 'bg-primary-500 text-white'
|
||||
|
|
@ -193,7 +233,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
All Games
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedGame('MTG')}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setSelectedGame('MTG');
|
||||
}}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
selectedGame === 'MTG'
|
||||
? 'bg-orange-500 text-white'
|
||||
|
|
@ -203,7 +248,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
Magic: The Gathering
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedGame('POKEMON')}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setSelectedGame('POKEMON');
|
||||
}}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
selectedGame === 'POKEMON'
|
||||
? 'bg-yellow-500 text-white'
|
||||
|
|
@ -213,7 +263,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
Pokémon
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedGame('YUGIOH')}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setSelectedGame('YUGIOH');
|
||||
}}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
selectedGame === 'YUGIOH'
|
||||
? 'bg-blue-500 text-white'
|
||||
|
|
@ -223,7 +278,12 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
Yu-Gi-Oh!
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedGame('LORCANA')}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setSelectedGame('LORCANA');
|
||||
}}
|
||||
className={`px-3 py-2 rounded-lg text-sm font-medium transition-colors whitespace-nowrap ${
|
||||
selectedGame === 'LORCANA'
|
||||
? 'bg-purple-500 text-white'
|
||||
|
|
@ -309,13 +369,23 @@ const CardDatabaseBrowser: React.FC<CardDatabaseBrowserProps> = ({
|
|||
{/* Actions */}
|
||||
<div className="flex flex-col space-y-2">
|
||||
<button
|
||||
onClick={() => handleCardClick(card)}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleCardClick(card);
|
||||
}}
|
||||
className="px-3 py-1 bg-primary-500 hover:bg-primary-600 text-white text-xs font-medium rounded-lg transition-colors"
|
||||
>
|
||||
Add to Collection
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleAddToDatabase(card)}
|
||||
type="button"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleAddToDatabase(card);
|
||||
}}
|
||||
disabled={addToDatabaseMutation.isPending}
|
||||
className="px-3 py-1 bg-surface-100 dark:bg-surface-700 hover:bg-surface-200 dark:hover:bg-surface-600 text-surface-700 dark:text-surface-300 text-xs font-medium rounded-lg transition-colors disabled:opacity-50"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -430,24 +430,34 @@ export const cardDataService = {
|
|||
async searchCards(query: string, game?: string): Promise<Card[]> {
|
||||
const results: Card[] = [];
|
||||
|
||||
console.log(`🔍 Unified search: "${query}" for game: "${game}"`);
|
||||
|
||||
try {
|
||||
if (!game || game === 'MTG') {
|
||||
console.log('🔍 Searching MTG...');
|
||||
const mtgCards = await mtgService.searchCards(query);
|
||||
console.log(`✅ Found ${mtgCards.length} MTG cards`);
|
||||
results.push(...mtgCards);
|
||||
}
|
||||
|
||||
if (!game || game === 'POKEMON') {
|
||||
console.log('🔍 Searching Pokémon...');
|
||||
const pokemonCards = await pokemonService.searchCards(query);
|
||||
console.log(`✅ Found ${pokemonCards.length} Pokémon cards`);
|
||||
results.push(...pokemonCards);
|
||||
}
|
||||
|
||||
if (!game || game === 'YUGIOH') {
|
||||
console.log('🔍 Searching Yu-Gi-Oh!...');
|
||||
const yugiohCards = await yugiohService.searchCards(query);
|
||||
console.log(`✅ Found ${yugiohCards.length} Yu-Gi-Oh! cards`);
|
||||
results.push(...yugiohCards);
|
||||
}
|
||||
|
||||
if (!game || game === 'LORCANA') {
|
||||
console.log('🔍 Searching Lorcana...');
|
||||
const lorcanaCards = await lorcanaService.searchCards(query);
|
||||
console.log(`✅ Found ${lorcanaCards.length} Lorcana cards`);
|
||||
results.push(...lorcanaCards);
|
||||
}
|
||||
|
||||
|
|
@ -456,6 +466,7 @@ export const cardDataService = {
|
|||
index === self.findIndex(c => c.name === card.name && c.game === card.game)
|
||||
);
|
||||
|
||||
console.log(`🎯 Total results: ${results.length}, Unique: ${uniqueCards.length}`);
|
||||
return uniqueCards;
|
||||
} catch (error) {
|
||||
console.error('Error in unified card search:', error);
|
||||
|
|
@ -504,21 +515,29 @@ export const cardDataService = {
|
|||
async getRandomCards(count = 20, game?: string): Promise<Card[]> {
|
||||
const results: Card[] = [];
|
||||
|
||||
console.log(`🎲 Getting ${count} random cards for game: "${game}"`);
|
||||
|
||||
try {
|
||||
if (!game || game === 'MTG') {
|
||||
console.log('🎲 Getting random MTG cards...');
|
||||
const mtgCards = await mtgService.getRandomCards(Math.ceil(count / 4));
|
||||
console.log(`✅ Found ${mtgCards.length} random MTG cards`);
|
||||
results.push(...mtgCards);
|
||||
}
|
||||
|
||||
if (!game || game === 'LORCANA') {
|
||||
console.log('🎲 Getting random Lorcana cards...');
|
||||
const lorcanaCards = await lorcanaService.getRandomCards(Math.ceil(count / 4));
|
||||
console.log(`✅ Found ${lorcanaCards.length} random Lorcana cards`);
|
||||
results.push(...lorcanaCards);
|
||||
}
|
||||
|
||||
// Note: Pokémon and Yu-Gi-Oh! APIs don't have random card endpoints
|
||||
// You could implement random selection from popular cards lists
|
||||
|
||||
return results.slice(0, count);
|
||||
const finalResults = results.slice(0, count);
|
||||
console.log(`🎯 Returning ${finalResults.length} random cards`);
|
||||
return finalResults;
|
||||
} catch (error) {
|
||||
console.error('Error getting random cards:', error);
|
||||
return [];
|
||||
|
|
|
|||
Loading…
Reference in a new issue