diff --git a/src/components/Community.tsx b/src/components/Community.tsx index 67ea0b9..088c7c6 100644 --- a/src/components/Community.tsx +++ b/src/components/Community.tsx @@ -62,6 +62,7 @@ export default function Community() { const [selectedUserCollection, setSelectedUserCollection] = useState([]); const [loadingCollection, setLoadingCollection] = useState(false); const [showTradeCreator, setShowTradeCreator] = useState(false); + const [userCollectionSearch, setUserCollectionSearch] = useState(''); // Friends state const [friendsSubTab, setFriendsSubTab] = useState('list'); @@ -382,13 +383,17 @@ export default function Community() { // ============ USER COLLECTION VIEW ============ if (selectedUser) { + const filteredUserCollection = selectedUserCollection.filter(({ card }) => + card.name.toLowerCase().includes(userCollectionSearch.toLowerCase()) + ); + return (
{/* Header */}
-
+
+ {/* Search input */} +
+ + setUserCollectionSearch(e.target.value)} + placeholder="Search cards..." + className="w-full pl-9 pr-8 py-2 bg-gray-700 border border-gray-600 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" + /> + {userCollectionSearch && ( + + )} +
{/* Collection Grid */} @@ -413,9 +437,11 @@ export default function Community() {
) : selectedUserCollection.length === 0 ? (

Empty collection

+ ) : filteredUserCollection.length === 0 ? ( +

No cards match "{userCollectionSearch}"

) : (
- {selectedUserCollection.map(({ card, quantity }) => ( + {filteredUserCollection.map(({ card, quantity }) => (
; + onAdd: (card: Card, maxQty: number) => void; + onRemove: (cardId: string) => void; + emptyMessage: string; + selectionColor: 'green' | 'blue'; + searchValue: string; + onSearchChange: (value: string) => void; + searchPlaceholder: string; +} + +function CollectionGrid({ + items, + selectedCards, + onAdd, + onRemove, + emptyMessage, + selectionColor, + searchValue, + onSearchChange, + searchPlaceholder, +}: CollectionGridProps) { + const ringColor = selectionColor === 'green' ? 'ring-green-500' : 'ring-blue-500'; + const badgeColor = selectionColor === 'green' ? 'bg-green-600' : 'bg-blue-500'; + + const filteredItems = items.filter(({ card }) => + card.name.toLowerCase().includes(searchValue.toLowerCase()) + ); + + return ( +
+
+ + onSearchChange(e.target.value)} + placeholder={searchPlaceholder} + className="w-full pl-9 pr-8 py-2 bg-gray-700 border border-gray-600 rounded-lg text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent" + /> + {searchValue && ( + + )} +
+ + {items.length === 0 ? ( +

{emptyMessage}

+ ) : filteredItems.length === 0 ? ( +

No cards match "{searchValue}"

+ ) : ( +
+ {filteredItems.map(({ card, quantity }) => { + const selected = selectedCards.get(card.id); + const remainingQty = quantity - (selected?.quantity || 0); + return ( +
remainingQty > 0 && onAdd(card, quantity)} + > + {card.name} +
+ {remainingQty}/{quantity} +
+ {selected && ( + + )} +
+ ); + })} +
+ )} +
+ ); +} + +interface SelectedCardsSummaryProps { + cards: Map; + onRemove: (cardId: string) => void; + label: string; + emptyLabel: string; + color: 'green' | 'blue'; +} + +function SelectedCardsSummary({ cards, onRemove, label, emptyLabel, color }: SelectedCardsSummaryProps) { + const bgColor = color === 'green' ? 'bg-green-900/50' : 'bg-blue-900/50'; + const textColor = color === 'green' ? 'text-green-400' : 'text-blue-400'; + + return ( +
+

{label}:

+ {cards.size === 0 ? ( +

{emptyLabel}

+ ) : ( +
+ {Array.from(cards.values()).map((item) => ( +
+ {item.card.name} + x{item.quantity} + +
+ ))} +
+ )} +
+ ); +} + +// ============ MAIN COMPONENT ============ + interface TradeCreatorProps { receiverId: string; receiverUsername: string; @@ -19,12 +166,6 @@ interface TradeCreatorProps { onTradeCreated: () => void; } -interface SelectedCard { - card: Card; - quantity: number; - maxQuantity: number; -} - type MobileStep = 'want' | 'give' | 'review'; export default function TradeCreator({ @@ -41,20 +182,19 @@ export default function TradeCreator({ const [submitting, setSubmitting] = useState(false); const [message, setMessage] = useState(''); - // Mobile step state const [isGiftMode, setIsGiftMode] = useState(false); const [mobileStep, setMobileStep] = useState('want'); - // Cards I'm offering (from my collection) const [myOfferedCards, setMyOfferedCards] = useState>(new Map()); - // Cards I want (from their collection) const [wantedCards, setWantedCards] = useState>(new Map()); + const [myCollectionSearch, setMyCollectionSearch] = useState(''); + const [theirCollectionSearch, setTheirCollectionSearch] = useState(''); + useEffect(() => { loadMyCollection(); }, [user]); - // When gift mode is toggled, adjust mobile step useEffect(() => { if (isGiftMode) { setWantedCards(new Map()); @@ -186,7 +326,6 @@ export default function TradeCreator({ const isGift = myOfferedCards.size > 0 && wantedCards.size === 0; const isRequest = myOfferedCards.size === 0 && wantedCards.size > 0; - // Mobile navigation const goToNextStep = () => { if (mobileStep === 'want') setMobileStep('give'); else if (mobileStep === 'give') setMobileStep('review'); @@ -197,123 +336,8 @@ export default function TradeCreator({ else if (mobileStep === 'give' && !isGiftMode) setMobileStep('want'); }; - const canGoNext = () => { - if (mobileStep === 'want') return true; // Can skip wanting cards (request nothing) - if (mobileStep === 'give') return true; // Can skip giving cards (gift request) - return false; - }; - const canSubmit = myOfferedCards.size > 0 || wantedCards.size > 0; - // Collection grid component - const CollectionGrid = ({ - items, - selectedCards, - onAdd, - onRemove, - emptyMessage, - selectionColor, - }: { - items: CollectionItem[]; - selectedCards: Map; - onAdd: (card: Card, maxQty: number) => void; - onRemove: (cardId: string) => void; - emptyMessage: string; - selectionColor: 'green' | 'blue'; - }) => { - if (items.length === 0) { - return

{emptyMessage}

; - } - - const ringColor = selectionColor === 'green' ? 'ring-green-500' : 'ring-blue-500'; - const badgeColor = selectionColor === 'green' ? 'bg-green-600' : 'bg-blue-500'; - - return ( -
- {items.map(({ card, quantity }) => { - const selected = selectedCards.get(card.id); - const remainingQty = quantity - (selected?.quantity || 0); - return ( -
remainingQty > 0 && onAdd(card, quantity)} - > - {card.name} -
- {remainingQty}/{quantity} -
- {selected && ( - - )} -
- ); - })} -
- ); - }; - - // Selected cards summary component - const SelectedCardsSummary = ({ - cards, - onRemove, - label, - emptyLabel, - color, - }: { - cards: Map; - onRemove: (cardId: string) => void; - label: string; - emptyLabel: string; - color: 'green' | 'blue'; - }) => { - const bgColor = color === 'green' ? 'bg-green-900/50' : 'bg-blue-900/50'; - const textColor = color === 'green' ? 'text-green-400' : 'text-blue-400'; - - return ( -
-

{label}:

- {cards.size === 0 ? ( -

{emptyLabel}

- ) : ( -
- {Array.from(cards.values()).map((item) => ( -
- {item.card.name} - x{item.quantity} - -
- ))} -
- )} -
- ); - }; - - // Loading state if (loading) { return (
@@ -328,7 +352,6 @@ export default function TradeCreator({ {/* ============ MOBILE VIEW ============ */}
- {/* Mobile Header */}
@@ -339,7 +362,6 @@ export default function TradeCreator({
- {/* Gift Toggle */}