From cc89c4908d82b3fa2d28b8e01fe4f577e980e9a3 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 11:25:58 +0100 Subject: [PATCH 01/52] factored out components used in editor and collection. preparing to remove editor --- packages/webapp/src/components/decklist.tsx | 32 +++ .../editor/cardCollectionDisplay.tsx | 57 +++++ .../webapp/src/components/editor/deckList.tsx | 34 +++ .../src/components/editor/deckPanel.tsx | 89 +++++++ .../src/components/editor/filterPanel.tsx | 84 +++++++ packages/webapp/src/pages/collection.tsx | 228 ++++++++++-------- 6 files changed, 419 insertions(+), 105 deletions(-) create mode 100644 packages/webapp/src/components/decklist.tsx create mode 100644 packages/webapp/src/components/editor/cardCollectionDisplay.tsx create mode 100644 packages/webapp/src/components/editor/deckList.tsx create mode 100644 packages/webapp/src/components/editor/deckPanel.tsx create mode 100644 packages/webapp/src/components/editor/filterPanel.tsx diff --git a/packages/webapp/src/components/decklist.tsx b/packages/webapp/src/components/decklist.tsx new file mode 100644 index 00000000..51169fe3 --- /dev/null +++ b/packages/webapp/src/components/decklist.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import Link from 'next/link'; +import { Deck } from 'src/store/types.ts'; + +interface DeckListProps { + decks: Deck[]; + onDeckSelect: (deckID: number) => void; +} + +const DeckList: React.FC = ({ decks, onDeckSelect }) => { + return ( +
+ {/* New Deck Button */} + + New Deck → + + + {/* Deck Buttons */} + {decks.map((deck, deckID) => ( + + ))} +
+ ); +}; + +export default DeckList; \ No newline at end of file diff --git a/packages/webapp/src/components/editor/cardCollectionDisplay.tsx b/packages/webapp/src/components/editor/cardCollectionDisplay.tsx new file mode 100644 index 00000000..00d4bc7e --- /dev/null +++ b/packages/webapp/src/components/editor/cardCollectionDisplay.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import Image from 'next/image' +import { Card } from 'src/store/types' +import { MintDeckModal } from 'src/components/modals/mintDeckModal' + +interface CardCollectionDisplayProps { + cards: Card[]; + isHydrated: boolean; + setSelectedCard: (card: Card | null) => void; + onCardToggle: (card: Card) => void; + selectedCards: Card[]; +} + +const CardCollectionDisplay: React.FC = ({ cards, isHydrated, refetch, setSelectedCard, selectedCards, onCardToggle }) => { + return ( + <> + + +
+ {isHydrated && cards.length === 0 && ( +
+ +
+ )} + + {isHydrated && cards.length > 0 && ( +
+ {cards.map(card => ( +
c.id === card.id) ? 'card-in-deck' : '' // Highlight if selected + } hover:bg-slate-800 rounded-lg p-4 border-4 border-slate-900`} + style={{ height: 'fit-content' }} + onMouseEnter={() => setSelectedCard(card)} + onClick={() => onCardToggle(card)} // Toggle card selection + > + {card.lore.name} +
{card.lore.name}
+
+
{card.stats.attack}
+
{card.stats.defense}
+
+
+ ))} +
+ )} +
+ + ) +} + +export default CardCollectionDisplay diff --git a/packages/webapp/src/components/editor/deckList.tsx b/packages/webapp/src/components/editor/deckList.tsx new file mode 100644 index 00000000..00c00404 --- /dev/null +++ b/packages/webapp/src/components/editor/deckList.tsx @@ -0,0 +1,34 @@ +import React from 'react' +import Link from 'next/link' +import { Deck } from 'src/store/types.ts' + +interface DeckListProps { + decks: Deck[] + onDeckSelect: (deckID: number) => void +} + +const DeckList: React.FC = ({ decks, onDeckSelect }) => { + return ( +
+ {/* New Deck Button */} + + New Deck → + + + {/* Deck Buttons */} + {decks.map((deck, deckID) => ( + + ))} +
+ ) +} + +export default DeckList \ No newline at end of file diff --git a/packages/webapp/src/components/editor/deckPanel.tsx b/packages/webapp/src/components/editor/deckPanel.tsx new file mode 100644 index 00000000..81424bfd --- /dev/null +++ b/packages/webapp/src/components/editor/deckPanel.tsx @@ -0,0 +1,89 @@ +import React, { useState } from 'react'; +import { Deck, Card } from 'src/store/types' + +interface DeckPanelProps { + deck: Deck + onCardSelect: (card: Card) => void + onSave: (deck: Deck) => void + onCancel: () => void + } + + const DeckPanel: React.FC = ({ deck, onCardSelect, onSave, onCancel }) => { + const [ deckName, setDeckName ] = useState(deck.name) + + const handleDeckNameChange = (event: React.ChangeEvent) => { + setDeckName(event.target.value) + } + + const handleSave = () => { + onSave({ ...deck, name: deckName }) + } + + const handleCancel = () => { + onCancel() + } + + return ( +
+ + + {/* Deck Name Input */} + + + {/* Save and Cancel Buttons */} +
+ + +
+ + {/* List of Cards in the Deck */} +
+ {deck.cards.map((card, index) => ( +
onCardSelect(card)} + > +
+ {card.name} + {card.name} +
+
+ ))} +
+
+ ); +}; + + +// Define default props +DeckPanel.defaultProps = { + deck: { + name: 'New Deck', + cards: [] + } + }; + +export default DeckPanel \ No newline at end of file diff --git a/packages/webapp/src/components/editor/filterPanel.tsx b/packages/webapp/src/components/editor/filterPanel.tsx new file mode 100644 index 00000000..43b00274 --- /dev/null +++ b/packages/webapp/src/components/editor/filterPanel.tsx @@ -0,0 +1,84 @@ +import React from 'react' +import Image from 'next/image' +import { Card } from 'src/store/types' + +interface FilterPanelProps { + effects: string[] + types: string[] + effectMap: { [key: string]: boolean } + typeMap: { [key: string]: boolean } + handleEffectClick: (index: number) => void + handleTypeClick: (index: number) => void + handleInputChange: (event: React.ChangeEvent) => void + selectedCard: Card | null +} + +const FilterPanel: React.FC = ({ + effects, + types, + effectMap, + typeMap, + handleEffectClick, + handleTypeClick, + handleInputChange, + selectedCard +}) => { + const cardName = selectedCard?.lore.name || "Select a card" + const cardFlavor = selectedCard?.lore.flavor || "Select a card to see its details" + + return ( +
+
+ {/* Search */} +

Search

+
+ +
+ + {/* Effects */} +

Effects

+
+ {effects.map((effect, index) => ( + ) + )} +
+ + {/* Types */} +

Types

+
+ {types.map((type, index) => ( + ) + )} +
+ + {/* todo @eviterin: makes sense to add a filter for the card collection display to only show one of each card. */} + + {/* Selected Card Display */} +
+

Card details

+
+ {cardName} +
{cardName}
+
+
{cardFlavor}
+
+
+
+ ) +} + +export default FilterPanel \ No newline at end of file diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 01a3fb91..92828603 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -3,7 +3,7 @@ import Head from "next/head" // This causes the "Ignoring unsupported entryTypes: largest-contentful-paint.", presumably // because Firefox does not support some associated features. import Image from "next/image" -import { useState, useMemo } from "react" +import { useState, useMemo, useEffect } from "react" import { useAccount } from "wagmi" import jotaiDebug from "src/components/lib/jotaiDebug" @@ -17,6 +17,11 @@ import { FablePage } from "src/pages/_app" import Link from "next/link" import { useRouter } from 'next/router' +import FilterPanel from 'src/components/editor/filterPanel' +import CardCollectionDisplay from 'src/components/editor/cardCollectionDisplay' +import DeckList from 'src/components/editor/deckList' +import DeckPanel from 'src/components/editor/deckPanel' + // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. @@ -35,6 +40,11 @@ const Collection: FablePage = ({ decks, isHydrated }) => { const [ searchInput, setSearchInput ] = useState('') const [ effectMap, setEffectMap ] = useState(initialEffectMap) const [ typeMap, setTypeMap ] = useState(initialTypeMap) + const [ isEditing, setIsEditing ] = useState(false) + const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }) + const [ originalDeckIndex, setOriginalDeckIndex ] = useState(null) + const [ deckCards, setDeckCards ] = useState([]); + const [selectedCards, setSelectedCards] = useState([]); const router = useRouter() @@ -79,6 +89,84 @@ const Collection: FablePage = ({ decks, isHydrated }) => { setTypeMap({...typeMap, [type]: !typeMap[type]}) } + const handleNewDeck = () => { + setCurrentDeck({ name: 'New Deck', cards: [] }); + setIsEditing(true); + setOriginalDeckIndex(null); + }; + + const handleDeckChange = (updatedDeck) => { + setIsEditing(false) + } + + const handleDeckSelect = (deckID) => { + const selectedDeck = decks[deckID] + setCurrentDeck(selectedDeck) + setOriginalDeckIndex(deckID) + setIsEditing(true) + } + + const handleSaveDeck = () => { + let updatedDecks = [...decks] + + if (originalDeckIndex !== null) { + updatedDecks[originalDeckIndex] = currentDeck + } else { + updatedDecks.push(currentDeck) + } + + setDecks(updatedDecks) + setIsEditing(false) + } + + const handleCancelEditing = () => { + setIsEditing(false); + } + + const addToDeck = (card: Card) => { + setDeck(prevDeck => { + const isAlreadyInDeck = prevDeck.some(cardInDeck => cardInDeck.id === card.id) + if (isAlreadyInDeck) { + // Remove the card from the deck + return prevDeck.filter(cardInDeck => cardInDeck.id !== card.id) + } else { + // Add the card to the deck + return [...prevDeck, card] + } + }) + } + + const toggleCardInDeck = (card) => { + setDeckCards((currentCards) => { + const isCardInDeck = currentCards.find((c) => c.id === card.id); + if (isCardInDeck) { + return currentCards.filter((c) => c.id !== card.id); + } else { + return [...currentCards, card]; + } + }); + }; + + const onCardToggle = (card: Card) => { + setSelectedCards((prevSelectedCards) => { + if (prevSelectedCards.some(selectedCard => selectedCard.id === card.id)) { + // Remove the card if it's already selected + return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id); + } else { + // Add the card if it's not already selected + return [...prevSelectedCards, card]; + } + }); + }; + + useEffect(() => { + if (router.query.newDeck) { + setCurrentDeck({ name: '', cards: [] }) + setIsEditing(true) + setOriginalDeckIndex(null) + } + }, [router.query.newDeck]) + return ( <> @@ -88,116 +176,46 @@ const Collection: FablePage = ({ decks, isHydrated }) => {
- - {/* Left Panel */} + {/* Left Panel - Search and Filters */}
-
- - {/* Search*/} -

Search

-
- -
- - {/*Effects*/} -

Effects

-
- {effects.map((effect, index) => { - const bgColor = effectMap[effect] ? 'bg-purple-900' : 'bg-gray-500' - return ( - ) - })} -
- - {/*Types*/} -

Types

-
- {types.map((type, index) => { - const bgColor = typeMap[type] ? 'bg-purple-900' : 'bg-gray-500' - return ( - ) - })} -
- - {/* Selected Card Display */} -
-

Card details

-
- {/*TODO handle the image*/} - {selectedCard?.lore.name -
{cardName}
-
-
{cardFlavor}
-
-
+
- {/* Card Collection Display */} + {/* Middle Panel - Card Collection Display */}
- { isHydrated && cards.length == 0 && -
- -
} - - { isHydrated && cards.length > 0 && -
- {cards.map(card => ( -
setSelectedCard(card)}> - {/*TODO handle the image*/} - {card.lore.name} -
{card.lore.name}
-
-
- {`${card.stats.attack}`} -
-
- {`${card.stats.defense}`} -
-
-
- ))} -
} +
- {/* Deck Panel */} -
-
- {/* New Deck Button */} - - New Deck → - - - {/* Deck Buttons */} - {decks.map((deck, deckID) => ( - - ))} -
+ {/* Right Panel - Deck List */} +
+ {isEditing ? ( + + ) : ( + + )}
From 1a23a29d91f68fbe4851f872dfbb9405fdec66be Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 14:15:31 +0100 Subject: [PATCH 02/52] Moved more save and cancel logic from editor to collection --- .../editor/cardCollectionDisplay.tsx | 8 +++- .../src/components/editor/deckPanel.tsx | 42 ++++++++--------- packages/webapp/src/pages/collection.tsx | 29 +++++++----- packages/webapp/src/pages/editor.tsx | 45 +++---------------- 4 files changed, 50 insertions(+), 74 deletions(-) diff --git a/packages/webapp/src/components/editor/cardCollectionDisplay.tsx b/packages/webapp/src/components/editor/cardCollectionDisplay.tsx index 00d4bc7e..8f001a68 100644 --- a/packages/webapp/src/components/editor/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/editor/cardCollectionDisplay.tsx @@ -11,7 +11,7 @@ interface CardCollectionDisplayProps { selectedCards: Card[]; } -const CardCollectionDisplay: React.FC = ({ cards, isHydrated, refetch, setSelectedCard, selectedCards, onCardToggle }) => { +const CardCollectionDisplay: React.FC = ({ cards, isHydrated, refetch, setSelectedCard, selectedCards, onCardToggle, isEditing }) => { return ( <> @@ -60,15 +62,15 @@ interface DeckPanelProps { {/* List of Cards in the Deck */}
- {deck.cards.map((card, index) => ( + {selectedCards.map((card, index) => (
onCardSelect(card)} >
- {card.name} - {card.name} + + {card.lore.name}
))} @@ -77,8 +79,6 @@ interface DeckPanelProps { ); }; - -// Define default props DeckPanel.defaultProps = { deck: { name: 'New Deck', diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 92828603..a049c139 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -33,7 +33,7 @@ const initialEffectMap = Object.assign({}, ...effects.map(name => ({[name]: fals const types = ['Creature', 'Magic', 'Weapon'] const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false}))) -const Collection: FablePage = ({ decks, isHydrated }) => { +const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { const { address } = useAccount() const [ selectedCard, setSelectedCard ] = useState(null) @@ -44,7 +44,7 @@ const Collection: FablePage = ({ decks, isHydrated }) => { const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }) const [ originalDeckIndex, setOriginalDeckIndex ] = useState(null) const [ deckCards, setDeckCards ] = useState([]); - const [selectedCards, setSelectedCards] = useState([]); + const [ selectedCards, setSelectedCards ] = useState([]); const router = useRouter() @@ -117,24 +117,27 @@ const Collection: FablePage = ({ decks, isHydrated }) => { setDecks(updatedDecks) setIsEditing(false) + setSelectedCards([]); + router.push('/collection'); } const handleCancelEditing = () => { setIsEditing(false); - } + setSelectedCards([]); + router.push('/collection'); + }; const addToDeck = (card: Card) => { - setDeck(prevDeck => { - const isAlreadyInDeck = prevDeck.some(cardInDeck => cardInDeck.id === card.id) - if (isAlreadyInDeck) { - // Remove the card from the deck - return prevDeck.filter(cardInDeck => cardInDeck.id !== card.id) + setSelectedCards(prevSelectedCards => { + // Add or remove card from the selectedCards + const isCardSelected = prevSelectedCards.some(selectedCard => selectedCard.id === card.id); + if (isCardSelected) { + return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id); } else { - // Add the card to the deck - return [...prevDeck, card] + return [...prevSelectedCards, card]; } - }) - } + }); + }; const toggleCardInDeck = (card) => { setDeckCards((currentCards) => { @@ -198,6 +201,7 @@ const Collection: FablePage = ({ decks, isHydrated }) => { setSelectedCard={setSelectedCard} onCardToggle={onCardToggle} selectedCards={selectedCards} + isEditing={isEditing} />
@@ -206,6 +210,7 @@ const Collection: FablePage = ({ decks, isHydrated }) => { {isEditing ? ( { {/* Deck Panel */}
- {/* name and save */} -
-
-
- - - - -
-
- - {/* Container for the Card Names */} -
- {deck.map((card, index) => ( -
removeFromDeck(index)} - onMouseEnter={() => setSelectedCard(card)} - > -
{card.lore.name}
-
- ))} -
-
+
From 6dfca99de14cd3545d7e27c474f9b895af8cd2c8 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 19:07:11 +0100 Subject: [PATCH 03/52] Migrated save and load functionality from editor. --- .../src/components/editor/deckPanel.tsx | 24 ++++++++++++-- packages/webapp/src/pages/collection.tsx | 32 +++++++++++-------- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/packages/webapp/src/components/editor/deckPanel.tsx b/packages/webapp/src/components/editor/deckPanel.tsx index 84d6b99d..e2359977 100644 --- a/packages/webapp/src/components/editor/deckPanel.tsx +++ b/packages/webapp/src/components/editor/deckPanel.tsx @@ -12,13 +12,31 @@ interface DeckPanelProps { const DeckPanel: React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { const [ deckName, setDeckName ] = useState(deck.name) + const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) const handleDeckNameChange = (event: React.ChangeEvent) => { setDeckName(event.target.value) + setIsDeckNameValid(true) } const handleSave = () => { - onSave({ ...deck, name: deckName }) + if(selectedCards.length === 0) { + // If no cards, then treat save as a cancel + onCancel() + return + } + + if (!deckName.trim()) { + setIsDeckNameValid(false) + return + } + + const newDeck = { + name: deckName, + cards: selectedCards + }; + + onSave(newDeck) } const handleCancel = () => { @@ -46,10 +64,11 @@ interface DeckPanelProps { `} {/* Deck Name Input */} - @@ -69,6 +88,7 @@ interface DeckPanelProps { onClick={() => onCardSelect(card)} >
+ {/* todo @eviterin: get proper link to the card instead of always the witch */} {card.lore.name}
diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index a049c139..f01fb9fd 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -100,26 +100,30 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { } const handleDeckSelect = (deckID) => { - const selectedDeck = decks[deckID] - setCurrentDeck(selectedDeck) - setOriginalDeckIndex(deckID) - setIsEditing(true) - } + const selectedDeck = decks[deckID]; + setCurrentDeck(selectedDeck); + setOriginalDeckIndex(deckID); + setIsEditing(true); + setSelectedCards(selectedDeck.cards); + }; - const handleSaveDeck = () => { - let updatedDecks = [...decks] - + const handleSaveDeck = (updatedDeck) => { + //console.log(updatedDeck); + let updatedDecks = [...decks]; + console.log(updatedDecks); if (originalDeckIndex !== null) { - updatedDecks[originalDeckIndex] = currentDeck + // Update the existing deck at the original index + updatedDecks[originalDeckIndex] = updatedDeck; } else { - updatedDecks.push(currentDeck) + // Add the new deck to the list + updatedDecks.push(updatedDeck); } - setDecks(updatedDecks) - setIsEditing(false) - setSelectedCards([]); + setDecks(updatedDecks); + setIsEditing(false); + setSelectedCards([]); router.push('/collection'); - } + }; const handleCancelEditing = () => { setIsEditing(false); From d66d9028f5426607e063540ee16eeaeb420eb507 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 19:09:56 +0100 Subject: [PATCH 04/52] Deleted 'editor.tsx' --- packages/webapp/src/pages/editor.tsx | 302 --------------------------- 1 file changed, 302 deletions(-) delete mode 100644 packages/webapp/src/pages/editor.tsx diff --git a/packages/webapp/src/pages/editor.tsx b/packages/webapp/src/pages/editor.tsx deleted file mode 100644 index a311c51c..00000000 --- a/packages/webapp/src/pages/editor.tsx +++ /dev/null @@ -1,302 +0,0 @@ -import debounce from "lodash/debounce" -import Head from "next/head" -// This causes the "Ignoring unsupported entryTypes: largest-contentful-paint.", presumably -// because Firefox does not support some associated features. -import Image from "next/image" -import { useState, useMemo } from "react" -import { useAccount } from "wagmi" - -import jotaiDebug from "src/components/lib/jotaiDebug" -import { MintDeckModal } from "src/components/modals/mintDeckModal" -import { Navbar } from "src/components/navbar" -import { deployment } from "src/deployment" -import { useInventoryCardsCollectionGetCollection } from "src/generated" -import { Card } from "src/store/types" -import { Address } from "src/chain" -import { FablePage } from "src/pages/_app" -import { useRouter } from 'next/router' -import { useEffect} from 'react' - -import DeckPanel from 'src/components/editor/deckPanel' - -// NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, -// fetch those from the chain instead of hardcoding them here. - -type Effect = string - -const effects: Effect[] = ['Charge', 'Flight', 'Courage', 'Undying', 'Frenzy', 'Enlightened'] -const initialEffectMap = Object.assign({}, ...effects.map(name => ({[name]: false}))) - -const types = ['Creature', 'Magic', 'Weapon'] -const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false}))) - -const Editor: FablePage = ({ decks, setDecks, isHydrated }) => { - const { address } = useAccount() - const [ selectedCard, setSelectedCard ] = useState(null) - const [ searchInput, setSearchInput ] = useState('') - const [ effectMap, setEffectMap ] = useState(initialEffectMap) - const [ typeMap, setTypeMap ] = useState(initialTypeMap) - const [ deckName, setDeckName ] = useState('') - const [ deck, setDeck ] = useState([]) - const [ originalDeckIndex, setOriginalDeckIndex ] = useState(null) - - const router = useRouter() - - const cardName = selectedCard?.lore.name || "Hover a card" - const cardFlavor = selectedCard?.lore.flavor || "Hover a card to see its details" - - const activeEffects = Object.keys(effectMap).filter(key => effectMap[key]) - const activeTypes = Object.keys(typeMap).filter(key => typeMap[key]) - - const [isDeckValid, setIsDeckValid] = useState(true) - - const { data: unfilteredCards, refetch } = useInventoryCardsCollectionGetCollection({ - address: deployment.InventoryCardsCollection, - args: [address as Address] // TODO not ideal but safe in practice - }) as { - // make the wagmi type soup understandable, there are many more fields in reality - data: readonly Card[], - refetch: () => Promise<{ data?: readonly Card[], error: Error|null }> - } - - const cards: Card[] = (unfilteredCards || []).filter(card => { - // TODO(norswap): it would look like this if the card had effects & types - // const cardEffects = card.stats.effects || [] - // const cardTypes = card.stats.types || [] - const cardEffects: Effect[] = [] - const cardTypes: Effect[] = [] - return activeEffects.every(effect => cardEffects.includes(effect)) - && activeTypes.every(type => cardTypes.includes(type)) - && card.lore.name.toLowerCase().includes(searchInput.toLowerCase()) - }) - - const addToDeck = (card: Card) => { - setDeck(prevDeck => { - const isAlreadyInDeck = prevDeck.some(cardInDeck => cardInDeck.id === card.id) - if (isAlreadyInDeck) { - // Remove the card from the deck - return prevDeck.filter(cardInDeck => cardInDeck.id !== card.id) - } else { - // Add the card to the deck - return [...prevDeck, card] - } - }) - } - - // Check url for an index, which is passed if the user wants to modify an existing deck - useEffect(() => { - if (typeof router.query.deckID === "string") { - const deckIndex = parseInt(router.query.deckID) - if (!isNaN(deckIndex) && decks[deckIndex] != null) { - setOriginalDeckIndex(deckIndex) // Store the original index - const selectedDeck = decks[deckIndex] - setDeckName(selectedDeck.name) - setDeck(selectedDeck.cards) - } else { - setOriginalDeckIndex(null) // Reset if not editing an existing deck - } - } - }, [router.query.deckID, decks]) - - const isCardInDeck = (cardToCheck: Card) => { - return deck.some(cardInDeck => cardInDeck.id === cardToCheck.id) - } - - const removeFromDeck = (index: number) => { - setDeck(prevDeck => prevDeck.filter((_, i) => i !== index)) - } - - const handleInputChangeBouncy = (event: React.ChangeEvent) => { - setSearchInput(event.target.value) - } - - const handleDeckNameChange = (event: React.ChangeEvent) => { - setDeckName(event.target.value) // Update deck name state - } - - const handleCancel = () => { - router.push('/collection') - } - - const handleSave = () => { - // Check if deck name is empty OR if the deck doesn't have any cards - if (!deckName.trim() || deck.length === 0) { - setIsDeckValid(false) - return - } - - setIsDeckValid(true) - - const updatedDecks = [...decks] - - // Check if editing an existing deck and the name has changed - if (originalDeckIndex !== null && decks[originalDeckIndex].name !== deckName) { - // Remove the old deck - updatedDecks.splice(originalDeckIndex, 1) - } - - // Find if a deck with the new name already exists - const existingDeckIndex = updatedDecks.findIndex(d => d.name === deckName) - - if (existingDeckIndex !== -1) { - // Replace existing deck with the new name - updatedDecks[existingDeckIndex] = { name: deckName, cards: deck } - } else { - // Add as a new deck - updatedDecks.push({ name: deckName, cards: deck }) - } - - setDecks(updatedDecks) - // Redirect to the collections page - router.push('/collection') - } - - const handleInputChange = useMemo(() => debounce(handleInputChangeBouncy, 300), []) - - const handleEffectClick = (effectIndex: number) => { - const effect = effects[effectIndex] - setEffectMap({...effectMap, [effect]: !effectMap[effect]}) - } - - const handleTypeClick = (typeIndex: number) => { - const type = types[typeIndex] - setTypeMap({...typeMap, [type]: !typeMap[type]}) - } - - return ( - <> - - 0xFable: My Collection - - - {jotaiDebug()} -
- -
- - {/* Left Panel */} -
-
- - {/* Search*/} -

Search

-
- -
- - {/*Effects*/} -

Effects

-
- {effects.map((effect, index) => { - const bgColor = effectMap[effect] ? 'bg-purple-900' : 'bg-gray-500' - return ( - ) - })} -
- - {/*Types*/} -

Types

-
- {types.map((type, index) => { - const bgColor = typeMap[type] ? 'bg-purple-900' : 'bg-gray-500' - return ( - ) - })} -
- - {/* Selected Card Display */} -
-

Card details

-
- {/*TODO handle the image*/} - {selectedCard?.lore.name -
{cardName}
-
-
{cardFlavor}
-
-
-
- - {/* Card Collection Display */} -
- { isHydrated && cards.length == 0 && -
- -
} - - { isHydrated && cards.length > 0 && -
- {cards.map(card => ( -
addToDeck(card)} - onMouseEnter={() => setSelectedCard(card)} - > - - {card.lore.name} -
{card.lore.name}
-
-
- {`${card.stats.attack}`} -
-
- {`${card.stats.defense}`} -
-
-
- - ))} -
} -
- - {/* Deck Panel */} -
- -
-
-
- - ) -} - -export default Editor \ No newline at end of file From 69ef67235b45a6e1da8030eee72b19be6a0fd487 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 19:20:56 +0100 Subject: [PATCH 05/52] Renamed components for sanity --- packages/webapp/src/components/decklist.tsx | 32 ------------------- ...deckList.tsx => deckCollectionDisplay.tsx} | 6 ++-- ...eckPanel.tsx => deckConstructionPanel.tsx} | 9 +++--- packages/webapp/src/pages/collection.tsx | 4 +-- 4 files changed, 10 insertions(+), 41 deletions(-) delete mode 100644 packages/webapp/src/components/decklist.tsx rename packages/webapp/src/components/editor/{deckList.tsx => deckCollectionDisplay.tsx} (83%) rename packages/webapp/src/components/editor/{deckPanel.tsx => deckConstructionPanel.tsx} (87%) diff --git a/packages/webapp/src/components/decklist.tsx b/packages/webapp/src/components/decklist.tsx deleted file mode 100644 index 51169fe3..00000000 --- a/packages/webapp/src/components/decklist.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import Link from 'next/link'; -import { Deck } from 'src/store/types.ts'; - -interface DeckListProps { - decks: Deck[]; - onDeckSelect: (deckID: number) => void; -} - -const DeckList: React.FC = ({ decks, onDeckSelect }) => { - return ( -
- {/* New Deck Button */} - - New Deck → - - - {/* Deck Buttons */} - {decks.map((deck, deckID) => ( - - ))} -
- ); -}; - -export default DeckList; \ No newline at end of file diff --git a/packages/webapp/src/components/editor/deckList.tsx b/packages/webapp/src/components/editor/deckCollectionDisplay.tsx similarity index 83% rename from packages/webapp/src/components/editor/deckList.tsx rename to packages/webapp/src/components/editor/deckCollectionDisplay.tsx index 00c00404..35e82ffa 100644 --- a/packages/webapp/src/components/editor/deckList.tsx +++ b/packages/webapp/src/components/editor/deckCollectionDisplay.tsx @@ -2,12 +2,12 @@ import React from 'react' import Link from 'next/link' import { Deck } from 'src/store/types.ts' -interface DeckListProps { +interface DeckCollectionDisplayProps { decks: Deck[] onDeckSelect: (deckID: number) => void } -const DeckList: React.FC = ({ decks, onDeckSelect }) => { +const DeckCollectionDisplay: React.FC = ({ decks, onDeckSelect }) => { return (
{/* New Deck Button */} @@ -31,4 +31,4 @@ const DeckList: React.FC = ({ decks, onDeckSelect }) => { ) } -export default DeckList \ No newline at end of file +export default DeckCollectionDisplay \ No newline at end of file diff --git a/packages/webapp/src/components/editor/deckPanel.tsx b/packages/webapp/src/components/editor/deckConstructionPanel.tsx similarity index 87% rename from packages/webapp/src/components/editor/deckPanel.tsx rename to packages/webapp/src/components/editor/deckConstructionPanel.tsx index e2359977..ddbce06d 100644 --- a/packages/webapp/src/components/editor/deckPanel.tsx +++ b/packages/webapp/src/components/editor/deckConstructionPanel.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import { Deck, Card } from 'src/store/types' -interface DeckPanelProps { +interface DeckConstructionPanelProps { deck: Deck; selectedCards: Card[]; onCardSelect: (card: Card) => void; @@ -10,7 +10,7 @@ interface DeckPanelProps { } - const DeckPanel: React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { + const DeckConstructionPanel : React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { const [ deckName, setDeckName ] = useState(deck.name) const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) @@ -22,6 +22,7 @@ interface DeckPanelProps { const handleSave = () => { if(selectedCards.length === 0) { // If no cards, then treat save as a cancel + // However, it could mean the player wants to delete their deck. onCancel() return } @@ -99,11 +100,11 @@ interface DeckPanelProps { ); }; -DeckPanel.defaultProps = { +DeckConstructionPanel.defaultProps = { deck: { name: 'New Deck', cards: [] } }; -export default DeckPanel \ No newline at end of file +export default DeckConstructionPanel \ No newline at end of file diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index f01fb9fd..5c55aa13 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -19,8 +19,8 @@ import { useRouter } from 'next/router' import FilterPanel from 'src/components/editor/filterPanel' import CardCollectionDisplay from 'src/components/editor/cardCollectionDisplay' -import DeckList from 'src/components/editor/deckList' -import DeckPanel from 'src/components/editor/deckPanel' +import DeckList from 'src/components/editor/deckCollectionDisplay' +import DeckPanel from 'src/components/editor/deckConstructionPanel' // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. From 0ff3fc6ba66603d87031d7640ee0cbf9c3d9500b Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 19:30:58 +0100 Subject: [PATCH 06/52] Grouped state variables by their function --- packages/webapp/src/pages/collection.tsx | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 5c55aa13..0ab38a8b 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -35,16 +35,22 @@ const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false})) const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { - const { address } = useAccount() - const [ selectedCard, setSelectedCard ] = useState(null) - const [ searchInput, setSearchInput ] = useState('') - const [ effectMap, setEffectMap ] = useState(initialEffectMap) - const [ typeMap, setTypeMap ] = useState(initialTypeMap) - const [ isEditing, setIsEditing ] = useState(false) - const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }) - const [ originalDeckIndex, setOriginalDeckIndex ] = useState(null) - const [ deckCards, setDeckCards ] = useState([]); - const [ selectedCards, setSelectedCards ] = useState([]); + const { address } = useAccount(); + const [ isDeckEditorActive, setIsDeckEditorActive ] = useState(false); + + // Filter Panel / Sorting Panel + const [ searchInput, setSearchInput ] = useState(''); + const [ effectMap, setEffectMap ] = useState(initialEffectMap); + const [ typeMap, setTypeMap ] = useState(initialTypeMap); + const [ selectedCard, setSelectedCard ] = useState(null); + + // Deck Collection Display + const [ userDecks, setUserDecks ] = useState([]); + const [ editingDeckIndex, setEditingDeckIndex ] = useState(null); + + // Deck Construction Panel + const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }); + const [ selectedDeckEditorCards, setSelectedDeckEditorCards ] = useState([]); const router = useRouter() @@ -108,9 +114,7 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { }; const handleSaveDeck = (updatedDeck) => { - //console.log(updatedDeck); let updatedDecks = [...decks]; - console.log(updatedDecks); if (originalDeckIndex !== null) { // Update the existing deck at the original index updatedDecks[originalDeckIndex] = updatedDeck; From a368f862406e77bc554ba28be8e11dc06732a221 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 19:47:29 +0100 Subject: [PATCH 07/52] refactored variable names --- packages/webapp/src/pages/collection.tsx | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 0ab38a8b..c72b297f 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -36,7 +36,7 @@ const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false})) const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { const { address } = useAccount(); - const [ isDeckEditorActive, setIsDeckEditorActive ] = useState(false); + const [ isEditing, setIsEditing ] = useState(false); // Filter Panel / Sorting Panel const [ searchInput, setSearchInput ] = useState(''); @@ -45,7 +45,7 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { const [ selectedCard, setSelectedCard ] = useState(null); // Deck Collection Display - const [ userDecks, setUserDecks ] = useState([]); + const [ userDecks, setUserDecks ] = useState([]); const [ editingDeckIndex, setEditingDeckIndex ] = useState(null); // Deck Construction Panel @@ -98,7 +98,7 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { const handleNewDeck = () => { setCurrentDeck({ name: 'New Deck', cards: [] }); setIsEditing(true); - setOriginalDeckIndex(null); + setEditingDeckIndex(null); }; const handleDeckChange = (updatedDeck) => { @@ -108,31 +108,31 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { const handleDeckSelect = (deckID) => { const selectedDeck = decks[deckID]; setCurrentDeck(selectedDeck); - setOriginalDeckIndex(deckID); + setEditingDeckIndex(deckID); setIsEditing(true); setSelectedCards(selectedDeck.cards); }; const handleSaveDeck = (updatedDeck) => { let updatedDecks = [...decks]; - if (originalDeckIndex !== null) { + if (editingDeckIndex !== null) { // Update the existing deck at the original index - updatedDecks[originalDeckIndex] = updatedDeck; + updatedDecks[editingDeckIndex] = updatedDeck; } else { // Add the new deck to the list updatedDecks.push(updatedDeck); } - + setDecks(updatedDecks); setIsEditing(false); setSelectedCards([]); - router.push('/collection'); + router.push('/collection'); }; const handleCancelEditing = () => { setIsEditing(false); - setSelectedCards([]); - router.push('/collection'); + setSelectedCards([]); + router.push('/collection'); }; const addToDeck = (card: Card) => { @@ -174,7 +174,7 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { if (router.query.newDeck) { setCurrentDeck({ name: '', cards: [] }) setIsEditing(true) - setOriginalDeckIndex(null) + setEditingDeckIndex(null) } }, [router.query.newDeck]) @@ -221,11 +221,11 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { selectedCards={selectedCards} onCardSelect={addToDeck} onSave={handleSaveDeck} - onCancel={handleCancelEditing} + onCancel={handleCancelEditing} /> ) : ( - )} @@ -236,4 +236,4 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { ) } -export default Collection \ No newline at end of file +export default Collection From e711cea41e02ee40e2cd0f022d8ac48233b2c722 Mon Sep 17 00:00:00 2001 From: eviterin Date: Fri, 19 Jan 2024 20:10:15 +0100 Subject: [PATCH 08/52] consistent css --- .../editor/deckConstructionPanel.tsx | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/webapp/src/components/editor/deckConstructionPanel.tsx b/packages/webapp/src/components/editor/deckConstructionPanel.tsx index ddbce06d..0c983836 100644 --- a/packages/webapp/src/components/editor/deckConstructionPanel.tsx +++ b/packages/webapp/src/components/editor/deckConstructionPanel.tsx @@ -64,20 +64,26 @@ interface DeckConstructionPanelProps { } `} - {/* Deck Name Input */} - - - {/* Save and Cancel Buttons */} -
- - +
+ {/* Deck Name Input */} + + + {/* Save and Cancel Buttons */} +
+ + +
{/* List of Cards in the Deck */} From d2f0de7edfd02277348faeffa7711e893c9f46db Mon Sep 17 00:00:00 2001 From: eviterin Date: Mon, 22 Jan 2024 11:17:48 +0100 Subject: [PATCH 09/52] Fixed all warnings with eslint and removed semicolons. --- .../editor/deckConstructionPanel.tsx | 47 +++--- packages/webapp/src/pages/_app.tsx | 6 +- packages/webapp/src/pages/collection.tsx | 135 ++++++++---------- 3 files changed, 80 insertions(+), 108 deletions(-) diff --git a/packages/webapp/src/components/editor/deckConstructionPanel.tsx b/packages/webapp/src/components/editor/deckConstructionPanel.tsx index 0c983836..15d709cf 100644 --- a/packages/webapp/src/components/editor/deckConstructionPanel.tsx +++ b/packages/webapp/src/components/editor/deckConstructionPanel.tsx @@ -1,12 +1,13 @@ -import React, { useState } from 'react'; +import React, { useState } from 'react' import { Deck, Card } from 'src/store/types' +import Image from 'next/image' interface DeckConstructionPanelProps { - deck: Deck; - selectedCards: Card[]; - onCardSelect: (card: Card) => void; - onSave: (deck: Deck) => void; - onCancel: () => void; + deck: Deck + selectedCards: Card[] + onCardSelect: (card: Card) => void + onSave: (deck: Deck) => void + onCancel: () => void } @@ -35,32 +36,28 @@ interface DeckConstructionPanelProps { const newDeck = { name: deckName, cards: selectedCards - }; + } onSave(newDeck) } - const handleCancel = () => { - onCancel() - } - return (
@@ -96,21 +93,21 @@ interface DeckConstructionPanelProps { >
{/* todo @eviterin: get proper link to the card instead of always the witch */} - + Card art {card.lore.name}
))}
- ); -}; + ) +} DeckConstructionPanel.defaultProps = { deck: { name: 'New Deck', cards: [] } - }; + } export default DeckConstructionPanel \ No newline at end of file diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index b3c7c95d..38ddeec1 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -77,10 +77,8 @@ const ComponentWrapper = ({ const isHydrated = useIsHydrated() const errorConfig = useErrorConfig() - // todo @eviterin: i've understood it so that decks are stored on chain. thus, below part is not going to be needed. - const _testCards = []; - const [decks, setDecks] = useState([]); - // + // todo @eviterin: to be removed when these decks are put onchain with https://github.com/0xFableOrg/0xFable/issues/103 + const [decks, setDecks] = useState([]) if (process.env.NODE_ENV === "development") { // constant // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index c72b297f..2161509b 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -1,20 +1,16 @@ import debounce from "lodash/debounce" import Head from "next/head" -// This causes the "Ignoring unsupported entryTypes: largest-contentful-paint.", presumably -// because Firefox does not support some associated features. -import Image from "next/image" + import { useState, useMemo, useEffect } from "react" import { useAccount } from "wagmi" import jotaiDebug from "src/components/lib/jotaiDebug" -import { MintDeckModal } from "src/components/modals/mintDeckModal" import { Navbar } from "src/components/navbar" import { deployment } from "src/deployment" import { useInventoryCardsCollectionGetCollection } from "src/generated" import { Card } from "src/store/types" import { Address } from "src/chain" import { FablePage } from "src/pages/_app" -import Link from "next/link" import { useRouter } from 'next/router' import FilterPanel from 'src/components/editor/filterPanel' @@ -24,9 +20,7 @@ import DeckPanel from 'src/components/editor/deckConstructionPanel' // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. - type Effect = string - const effects: Effect[] = ['Charge', 'Flight', 'Courage', 'Undying', 'Frenzy', 'Enlightened'] const initialEffectMap = Object.assign({}, ...effects.map(name => ({[name]: false}))) @@ -35,38 +29,32 @@ const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false})) const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { - const { address } = useAccount(); - const [ isEditing, setIsEditing ] = useState(false); + const router = useRouter() + const { address } = useAccount() + const [ isEditing, setIsEditing ] = useState(false) // Filter Panel / Sorting Panel - const [ searchInput, setSearchInput ] = useState(''); - const [ effectMap, setEffectMap ] = useState(initialEffectMap); - const [ typeMap, setTypeMap ] = useState(initialTypeMap); - const [ selectedCard, setSelectedCard ] = useState(null); + const [ searchInput, setSearchInput ] = useState('') + const [ effectMap, setEffectMap ] = useState(initialEffectMap) + const [ typeMap, setTypeMap ] = useState(initialTypeMap) + const [ selectedCard, setSelectedCard ] = useState(null) // Deck Collection Display - const [ userDecks, setUserDecks ] = useState([]); - const [ editingDeckIndex, setEditingDeckIndex ] = useState(null); + const [ editingDeckIndex, setEditingDeckIndex ] = useState(null) // Deck Construction Panel - const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }); - const [ selectedDeckEditorCards, setSelectedDeckEditorCards ] = useState([]); - - const router = useRouter() - - const cardName = selectedCard?.lore.name || "Select a card" - const cardFlavor = selectedCard?.lore.flavor || "Select a card to see its details" + const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }) + const [ selectedCards, setSelectedCards ] = useState([]) const activeEffects = Object.keys(effectMap).filter(key => effectMap[key]) const activeTypes = Object.keys(typeMap).filter(key => typeMap[key]) - const { data: unfilteredCards, refetch } = useInventoryCardsCollectionGetCollection({ + const { data: unfilteredCards } = useInventoryCardsCollectionGetCollection({ address: deployment.InventoryCardsCollection, args: [address as Address] // TODO not ideal but safe in practice }) as { // make the wagmi type soup understandable, there are many more fields in reality data: readonly Card[], - refetch: () => Promise<{ data?: readonly Card[], error: Error|null }> } const cards: Card[] = (unfilteredCards || []).filter(card => { @@ -95,88 +83,77 @@ const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { setTypeMap({...typeMap, [type]: !typeMap[type]}) } - const handleNewDeck = () => { - setCurrentDeck({ name: 'New Deck', cards: [] }); - setIsEditing(true); - setEditingDeckIndex(null); - }; - - const handleDeckChange = (updatedDeck) => { - setIsEditing(false) - } - const handleDeckSelect = (deckID) => { - const selectedDeck = decks[deckID]; - setCurrentDeck(selectedDeck); - setEditingDeckIndex(deckID); - setIsEditing(true); - setSelectedCards(selectedDeck.cards); - }; + const selectedDeck = decks[deckID] + setCurrentDeck(selectedDeck) + setEditingDeckIndex(deckID) + setIsEditing(true) + setSelectedCards(selectedDeck.cards) + } const handleSaveDeck = (updatedDeck) => { - let updatedDecks = [...decks]; + const updatedDecks = [...decks] if (editingDeckIndex !== null) { - // Update the existing deck at the original index - updatedDecks[editingDeckIndex] = updatedDeck; + // Update existing deck + updatedDecks[editingDeckIndex] = updatedDeck } else { // Add the new deck to the list - updatedDecks.push(updatedDeck); + updatedDecks.push(updatedDeck) } - - setDecks(updatedDecks); - setIsEditing(false); - setSelectedCards([]); - router.push('/collection'); - }; + setDecks(updatedDecks) + setIsEditing(false) + setSelectedCards([]) + router.push('/collection') + } const handleCancelEditing = () => { - setIsEditing(false); - setSelectedCards([]); - router.push('/collection'); - }; + setIsEditing(false) + setSelectedCards([]) + router.push('/collection') + } const addToDeck = (card: Card) => { setSelectedCards(prevSelectedCards => { // Add or remove card from the selectedCards - const isCardSelected = prevSelectedCards.some(selectedCard => selectedCard.id === card.id); + const isCardSelected = prevSelectedCards.some(selectedCard => selectedCard.id === card.id) if (isCardSelected) { - return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id); + return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id) } else { - return [...prevSelectedCards, card]; + return [...prevSelectedCards, card] } - }); - }; - - const toggleCardInDeck = (card) => { - setDeckCards((currentCards) => { - const isCardInDeck = currentCards.find((c) => c.id === card.id); - if (isCardInDeck) { - return currentCards.filter((c) => c.id !== card.id); - } else { - return [...currentCards, card]; - } - }); - }; + }) + } const onCardToggle = (card: Card) => { setSelectedCards((prevSelectedCards) => { if (prevSelectedCards.some(selectedCard => selectedCard.id === card.id)) { // Remove the card if it's already selected - return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id); + return prevSelectedCards.filter(selectedCard => selectedCard.id !== card.id) } else { // Add the card if it's not already selected - return [...prevSelectedCards, card]; + return [...prevSelectedCards, card] } - }); - }; + }) + } + + // Sets up an event listener for route changes when deck editor is rendered. useEffect(() => { - if (router.query.newDeck) { - setCurrentDeck({ name: '', cards: [] }) - setIsEditing(true) - setEditingDeckIndex(null) + const handleRouteChange = () => { + if (router.query.newDeck) { + setCurrentDeck({ name: '', cards: [] }) + setIsEditing(true) + setEditingDeckIndex(null) + } + } + + router.events.on('routeChangeComplete', handleRouteChange) + + // Clean up the event listener when exiting the deck editor. + return () => { + router.events.off('routeChangeComplete', handleRouteChange) } - }, [router.query.newDeck]) + }, [router.events, router.query.newDeck]) return ( <> From b6cb6a39e571f55d039f4b8d039e4f994ce4c683 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 23 Jan 2024 12:44:25 +0100 Subject: [PATCH 10/52] Renamed dir 'editor' to 'collection' --- .../components/{editor => collection}/cardCollectionDisplay.tsx | 0 .../components/{editor => collection}/deckCollectionDisplay.tsx | 0 .../components/{editor => collection}/deckConstructionPanel.tsx | 0 .../webapp/src/components/{editor => collection}/filterPanel.tsx | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename packages/webapp/src/components/{editor => collection}/cardCollectionDisplay.tsx (100%) rename packages/webapp/src/components/{editor => collection}/deckCollectionDisplay.tsx (100%) rename packages/webapp/src/components/{editor => collection}/deckConstructionPanel.tsx (100%) rename packages/webapp/src/components/{editor => collection}/filterPanel.tsx (100%) diff --git a/packages/webapp/src/components/editor/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx similarity index 100% rename from packages/webapp/src/components/editor/cardCollectionDisplay.tsx rename to packages/webapp/src/components/collection/cardCollectionDisplay.tsx diff --git a/packages/webapp/src/components/editor/deckCollectionDisplay.tsx b/packages/webapp/src/components/collection/deckCollectionDisplay.tsx similarity index 100% rename from packages/webapp/src/components/editor/deckCollectionDisplay.tsx rename to packages/webapp/src/components/collection/deckCollectionDisplay.tsx diff --git a/packages/webapp/src/components/editor/deckConstructionPanel.tsx b/packages/webapp/src/components/collection/deckConstructionPanel.tsx similarity index 100% rename from packages/webapp/src/components/editor/deckConstructionPanel.tsx rename to packages/webapp/src/components/collection/deckConstructionPanel.tsx diff --git a/packages/webapp/src/components/editor/filterPanel.tsx b/packages/webapp/src/components/collection/filterPanel.tsx similarity index 100% rename from packages/webapp/src/components/editor/filterPanel.tsx rename to packages/webapp/src/components/collection/filterPanel.tsx From 67636a19cea682c4c7fe6574f95a66c752e21c2f Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 23 Jan 2024 12:48:01 +0100 Subject: [PATCH 11/52] renamed import to reflect directory name update --- packages/webapp/src/pages/collection.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 2161509b..199442fd 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -13,10 +13,10 @@ import { Address } from "src/chain" import { FablePage } from "src/pages/_app" import { useRouter } from 'next/router' -import FilterPanel from 'src/components/editor/filterPanel' -import CardCollectionDisplay from 'src/components/editor/cardCollectionDisplay' -import DeckList from 'src/components/editor/deckCollectionDisplay' -import DeckPanel from 'src/components/editor/deckConstructionPanel' +import FilterPanel from 'src/components/collection/filterPanel' +import CardCollectionDisplay from 'src/components/collection/cardCollectionDisplay' +import DeckList from 'src/components/collection/deckCollectionDisplay' +import DeckPanel from 'src/components/collection/deckConstructionPanel' // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. From e7fa29636622c73c04c300a4fff12e7cdd728014 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 23 Jan 2024 17:40:18 +0100 Subject: [PATCH 12/52] Allow player to save empty deck --- .../src/components/collection/deckConstructionPanel.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/webapp/src/components/collection/deckConstructionPanel.tsx b/packages/webapp/src/components/collection/deckConstructionPanel.tsx index 15d709cf..f2294a23 100644 --- a/packages/webapp/src/components/collection/deckConstructionPanel.tsx +++ b/packages/webapp/src/components/collection/deckConstructionPanel.tsx @@ -21,13 +21,6 @@ interface DeckConstructionPanelProps { } const handleSave = () => { - if(selectedCards.length === 0) { - // If no cards, then treat save as a cancel - // However, it could mean the player wants to delete their deck. - onCancel() - return - } - if (!deckName.trim()) { setIsDeckNameValid(false) return From c85e05074b66d8dd175316c076f47593487aa97f Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 23 Jan 2024 19:23:56 +0100 Subject: [PATCH 13/52] Component wrapping 'Link' added to carry the '?index=' parameter used for testing. --- .../webapp/src/components/queryParamList.tsx | 25 +++++++++++++ packages/webapp/src/pages/index.tsx | 37 ++++++++----------- 2 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 packages/webapp/src/components/queryParamList.tsx diff --git a/packages/webapp/src/components/queryParamList.tsx b/packages/webapp/src/components/queryParamList.tsx new file mode 100644 index 00000000..59e125bd --- /dev/null +++ b/packages/webapp/src/components/queryParamList.tsx @@ -0,0 +1,25 @@ +import { useRouter } from 'next/router' +import Link from "next/link" + +/** + * A Link component wrapper that appends a 'index' query parameter to the URL in development mode. + * This is used to persist state across navigation during testing. + */ +const QueryParamLink = ({ children, href, ...props }) => { + const router = useRouter() + + let url = href + + if (process.env.NODE_ENV === "development") { + const index = parseInt(router.query.index as string) + if (index !== undefined && !isNaN(index) && 0 <= index && index <= 9) + url = url + (url.includes("?") ? "&" : "?") + `index=${index}` + } + return ( + + {children} + + ) +} + +export default QueryParamLink \ No newline at end of file diff --git a/packages/webapp/src/pages/index.tsx b/packages/webapp/src/pages/index.tsx index 5e6a6533..9fe23a9a 100644 --- a/packages/webapp/src/pages/index.tsx +++ b/packages/webapp/src/pages/index.tsx @@ -1,5 +1,4 @@ import { ConnectKitButton, useModal } from "connectkit" -import Link from "next/link" import { useAccount, useNetwork } from "wagmi" import { Address, chains } from "src/chain" @@ -10,7 +9,11 @@ import { MintDeckModal } from "src/components/modals/mintDeckModal" import { useGameInGame } from "src/generated" import { FablePage } from "src/pages/_app" import { useGameID } from "src/store/hooks" +<<<<<<< HEAD import { Button } from "src/components/ui/button" +======= +import QueryParamLink from "src/components/queryParamList" +>>>>>>> 4d68b23 (Component wrapping 'Link' added to carry the '?index=' parameter used for testing.) const Home: FablePage = ({ isHydrated }) => { const { address } = useAccount() @@ -54,27 +57,19 @@ const Home: FablePage = ({ isHydrated }) => { {isWrongNetwork && } - {isRightNetwork && ( - <> -
- - - - - - - - - -
- - - - )} + + + + + } ) From da488dae92a42ca67bc2de9b928665b675c08ffb Mon Sep 17 00:00:00 2001 From: eviterin Date: Wed, 24 Jan 2024 17:55:02 +0100 Subject: [PATCH 14/52] Removed unused css --- .../collection/deckConstructionPanel.tsx | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/packages/webapp/src/components/collection/deckConstructionPanel.tsx b/packages/webapp/src/components/collection/deckConstructionPanel.tsx index f2294a23..663bc0cf 100644 --- a/packages/webapp/src/components/collection/deckConstructionPanel.tsx +++ b/packages/webapp/src/components/collection/deckConstructionPanel.tsx @@ -36,24 +36,6 @@ interface DeckConstructionPanelProps { return (
- -
{/* Deck Name Input */} Date: Sat, 27 Jan 2024 21:21:11 +0100 Subject: [PATCH 15/52] renamed queryParamLink to just link. --- .../src/components/{queryParamList.tsx => link.tsx} | 2 +- packages/webapp/src/pages/index.tsx | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) rename packages/webapp/src/components/{queryParamList.tsx => link.tsx} (92%) diff --git a/packages/webapp/src/components/queryParamList.tsx b/packages/webapp/src/components/link.tsx similarity index 92% rename from packages/webapp/src/components/queryParamList.tsx rename to packages/webapp/src/components/link.tsx index 59e125bd..58102b0d 100644 --- a/packages/webapp/src/components/queryParamList.tsx +++ b/packages/webapp/src/components/link.tsx @@ -16,7 +16,7 @@ const QueryParamLink = ({ children, href, ...props }) => { url = url + (url.includes("?") ? "&" : "?") + `index=${index}` } return ( - + {children} ) diff --git a/packages/webapp/src/pages/index.tsx b/packages/webapp/src/pages/index.tsx index 9fe23a9a..48256f94 100644 --- a/packages/webapp/src/pages/index.tsx +++ b/packages/webapp/src/pages/index.tsx @@ -9,11 +9,8 @@ import { MintDeckModal } from "src/components/modals/mintDeckModal" import { useGameInGame } from "src/generated" import { FablePage } from "src/pages/_app" import { useGameID } from "src/store/hooks" -<<<<<<< HEAD import { Button } from "src/components/ui/button" -======= -import QueryParamLink from "src/components/queryParamList" ->>>>>>> 4d68b23 (Component wrapping 'Link' added to carry the '?index=' parameter used for testing.) +import Link from "src/components/link" const Home: FablePage = ({ isHydrated }) => { const { address } = useAccount() @@ -62,11 +59,11 @@ const Home: FablePage = ({ isHydrated }) => { - + - +
} From 36e70d5bc88e0d0500b48a4ee4d8ed1d963d47fd Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:25:05 +0100 Subject: [PATCH 16/52] updated comment on how to carry over the index query param --- packages/webapp/src/pages/_app.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 38ddeec1..86aa56bc 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -95,8 +95,9 @@ const ComponentWrapper = ({ // will ignore our existence and try to override us with their own account (depending on how // async code scheduling ends up working out). - // To carry the `index` query parameter to other parts of the app, be sure to use the `navigate` - // function from `utils/navigate.ts` instead of `router.push`. + // To carry the `index` query parameter to other parts of the app, be sure to either: + // - use the `navigate` function from `utils/navigate.ts` instead of `router.push`. + // - the `link` component from `components/link.tsx` instead of `next/link` } return <> From 05d0817d020f2847610d5e8506e42064fe7b5ffc Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:28:28 +0100 Subject: [PATCH 17/52] minor typo --- packages/webapp/src/pages/_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 86aa56bc..b6cad16d 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -97,7 +97,7 @@ const ComponentWrapper = ({ // To carry the `index` query parameter to other parts of the app, be sure to either: // - use the `navigate` function from `utils/navigate.ts` instead of `router.push`. - // - the `link` component from `components/link.tsx` instead of `next/link` + // - use the `link` component from `components/link.tsx` instead of `next/link` } return <> From 8b21444fd0abc7a319d8698c05c5fa0d41611dea Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:28:44 +0100 Subject: [PATCH 18/52] minor typo --- packages/webapp/src/pages/_app.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index b6cad16d..5388d9eb 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -95,9 +95,9 @@ const ComponentWrapper = ({ // will ignore our existence and try to override us with their own account (depending on how // async code scheduling ends up working out). - // To carry the `index` query parameter to other parts of the app, be sure to either: - // - use the `navigate` function from `utils/navigate.ts` instead of `router.push`. - // - use the `link` component from `components/link.tsx` instead of `next/link` + // To carry the `index` query parameter to other parts of the app, be sure to either use: + // - the `navigate` function from `utils/navigate.ts` instead of `router.push`. + // - the `link` component from `components/link.tsx` instead of `next/link` } return <> From d4f508b877850d4fe8f47f274a4eafd3e6e2ddad Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:33:56 +0100 Subject: [PATCH 19/52] file renames and import updates --- .../collection/{deckCollectionDisplay.tsx => deckList.tsx} | 0 .../collection/{deckConstructionPanel.tsx => deckPanel.tsx} | 0 packages/webapp/src/pages/collection.tsx | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/webapp/src/components/collection/{deckCollectionDisplay.tsx => deckList.tsx} (100%) rename packages/webapp/src/components/collection/{deckConstructionPanel.tsx => deckPanel.tsx} (100%) diff --git a/packages/webapp/src/components/collection/deckCollectionDisplay.tsx b/packages/webapp/src/components/collection/deckList.tsx similarity index 100% rename from packages/webapp/src/components/collection/deckCollectionDisplay.tsx rename to packages/webapp/src/components/collection/deckList.tsx diff --git a/packages/webapp/src/components/collection/deckConstructionPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx similarity index 100% rename from packages/webapp/src/components/collection/deckConstructionPanel.tsx rename to packages/webapp/src/components/collection/deckPanel.tsx diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 199442fd..189d3203 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -15,8 +15,8 @@ import { useRouter } from 'next/router' import FilterPanel from 'src/components/collection/filterPanel' import CardCollectionDisplay from 'src/components/collection/cardCollectionDisplay' -import DeckList from 'src/components/collection/deckCollectionDisplay' -import DeckPanel from 'src/components/collection/deckConstructionPanel' +import DeckList from 'src/components/collection/deckList' +import DeckPanel from 'src/components/collection/deckPanel' // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. From 109500a14e85c9756fb067380b5a3a36d3fad35a Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:34:53 +0100 Subject: [PATCH 20/52] readded the props to to keep css. --- packages/webapp/src/components/link.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index 58102b0d..59e125bd 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -16,7 +16,7 @@ const QueryParamLink = ({ children, href, ...props }) => { url = url + (url.includes("?") ? "&" : "?") + `index=${index}` } return ( - + {children} ) From 168087a0d3ea12f3fcba90888aff5488503f68d6 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:45:16 +0100 Subject: [PATCH 21/52] added deck name validity check for just spaces --- packages/webapp/src/components/collection/deckPanel.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 663bc0cf..11cbbeb6 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -13,15 +13,18 @@ interface DeckConstructionPanelProps { const DeckConstructionPanel : React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { const [ deckName, setDeckName ] = useState(deck.name) - const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) + const [ isDeckNameValid, setIsDeckNameValid ] = useState(false) const handleDeckNameChange = (event: React.ChangeEvent) => { + const newName = event.target.value; setDeckName(event.target.value) - setIsDeckNameValid(true) + setIsDeckNameValid(nameValid(newName)); } + const nameValid = (name) => name.trim().length > 0; + const handleSave = () => { - if (!deckName.trim()) { + if (!nameValid(deckName)) { setIsDeckNameValid(false) return } From 3080773d7657c2b3f2f9960f5630d5eda5b63e9b Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 21:46:55 +0100 Subject: [PATCH 22/52] added trim and set deck name to be valid as an initial state --- packages/webapp/src/components/collection/deckPanel.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 11cbbeb6..e3fdd24d 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -13,7 +13,7 @@ interface DeckConstructionPanelProps { const DeckConstructionPanel : React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { const [ deckName, setDeckName ] = useState(deck.name) - const [ isDeckNameValid, setIsDeckNameValid ] = useState(false) + const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) const handleDeckNameChange = (event: React.ChangeEvent) => { const newName = event.target.value; @@ -30,7 +30,7 @@ interface DeckConstructionPanelProps { } const newDeck = { - name: deckName, + name: deckName.trim(), cards: selectedCards } From b1ce4ba21c49455861abdd35d85590fd130fc66d Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 22:07:54 +0100 Subject: [PATCH 23/52] removed unneeded default props --- packages/webapp/src/components/collection/deckPanel.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index e3fdd24d..51eeb381 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -81,11 +81,4 @@ interface DeckConstructionPanelProps { ) } -DeckConstructionPanel.defaultProps = { - deck: { - name: 'New Deck', - cards: [] - } - } - export default DeckConstructionPanel \ No newline at end of file From de6fc70ba72f49edb87d55b90e74759cddb7d089 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 22:43:48 +0100 Subject: [PATCH 24/52] Added custom tailwind box shadow --- .../src/components/collection/cardCollectionDisplay.tsx | 8 +------- packages/webapp/tailwind.config.cjs | 6 ++++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 8f001a68..7d303788 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -14,12 +14,6 @@ interface CardCollectionDisplayProps { const CardCollectionDisplay: React.FC = ({ cards, isHydrated, refetch, setSelectedCard, selectedCards, onCardToggle, isEditing }) => { return ( <> - -
{isHydrated && cards.length === 0 && (
@@ -33,7 +27,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is
c.id === card.id) ? 'card-in-deck' : '' // Highlight if selected + selectedCards.some(c => c.id === card.id) ? 'shadow-highlight shadow-orange-300' : '' // Highlight if selected } hover:bg-slate-800 rounded-lg p-4 border-4 border-slate-900`} style={{ height: 'fit-content' }} onMouseEnter={() => setSelectedCard(card)} diff --git a/packages/webapp/tailwind.config.cjs b/packages/webapp/tailwind.config.cjs index 04eb984a..ca9541d0 100644 --- a/packages/webapp/tailwind.config.cjs +++ b/packages/webapp/tailwind.config.cjs @@ -71,6 +71,12 @@ module.exports = { "accordion-down": "accordion-down 0.2s ease-out", "accordion-up": "accordion-up 0.2s ease-out", }, + // Custom box shadow that adds a 'highlight' effect + // For example, add 'shadow-highlight shadow-orange-300' to className + // See: https://tailwindcss.com/docs/box-shadow#customizing-your-theme + boxShadow: { + 'highlight': '0 0 20px', + }, }, }, plugins: [require("tailwindcss-animate")], From 474592aacfee286f582fd653a081be4ba0a917fb Mon Sep 17 00:00:00 2001 From: eviterin Date: Sat, 27 Jan 2024 22:49:45 +0100 Subject: [PATCH 25/52] Dynamic card resize in collectionDisplay as per Norswap's recipe --- .../src/components/collection/cardCollectionDisplay.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 7d303788..7cf5fcee 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -22,14 +22,13 @@ const CardCollectionDisplay: React.FC = ({ cards, is )} {isHydrated && cards.length > 0 && ( -
+
{cards.map(card => (
c.id === card.id) ? 'shadow-highlight shadow-orange-300' : '' // Highlight if selected - } hover:bg-slate-800 rounded-lg p-4 border-4 border-slate-900`} - style={{ height: 'fit-content' }} + } hover:bg-slate-800 rounded-lg p-4 border-4 border-slate-900 grow w-[220px] max-w-[330px]`} onMouseEnter={() => setSelectedCard(card)} onClick={() => { if (isEditing) { @@ -37,7 +36,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is } }} > - {card.lore.name} + {card.lore.name}
{card.lore.name}
{card.stats.attack}
From 0c01ce5825f382c2ea4e768715b275512d8eaebb Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 01:25:27 +0100 Subject: [PATCH 26/52] remove semicolons --- .../collection/cardCollectionDisplay.tsx | 17 +++++++++-------- .../src/components/collection/deckList.tsx | 2 +- .../src/components/collection/deckPanel.tsx | 6 +++--- packages/webapp/src/components/link.tsx | 12 ++++++++++-- packages/webapp/src/pages/_app.tsx | 4 ++-- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 7cf5fcee..3de58294 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -4,20 +4,21 @@ import { Card } from 'src/store/types' import { MintDeckModal } from 'src/components/modals/mintDeckModal' interface CardCollectionDisplayProps { - cards: Card[]; - isHydrated: boolean; - setSelectedCard: (card: Card | null) => void; - onCardToggle: (card: Card) => void; - selectedCards: Card[]; + cards: Card[] + isHydrated: boolean + setSelectedCard: (card: Card | null) => void + onCardToggle: (card: Card) => void + selectedCards: Card[] + isEditing: boolean } -const CardCollectionDisplay: React.FC = ({ cards, isHydrated, refetch, setSelectedCard, selectedCards, onCardToggle, isEditing }) => { +const CardCollectionDisplay: React.FC = ({ cards, isHydrated, setSelectedCard, selectedCards, onCardToggle, isEditing }) => { return ( <>
{isHydrated && cards.length === 0 && (
- +
)} @@ -32,7 +33,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is onMouseEnter={() => setSelectedCard(card)} onClick={() => { if (isEditing) { - onCardToggle(card); // Only toggle card selection when in editing mode + onCardToggle(card) // Only toggle card selection when in editing mode } }} > diff --git a/packages/webapp/src/components/collection/deckList.tsx b/packages/webapp/src/components/collection/deckList.tsx index 35e82ffa..3a0c1387 100644 --- a/packages/webapp/src/components/collection/deckList.tsx +++ b/packages/webapp/src/components/collection/deckList.tsx @@ -1,6 +1,6 @@ import React from 'react' import Link from 'next/link' -import { Deck } from 'src/store/types.ts' +import { Deck } from 'src/store/types' interface DeckCollectionDisplayProps { decks: Deck[] diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 51eeb381..8c411a8a 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -16,12 +16,12 @@ interface DeckConstructionPanelProps { const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) const handleDeckNameChange = (event: React.ChangeEvent) => { - const newName = event.target.value; + const newName = event.target.value setDeckName(event.target.value) - setIsDeckNameValid(nameValid(newName)); + setIsDeckNameValid(nameValid(newName)) } - const nameValid = (name) => name.trim().length > 0; + const nameValid = (name: string) => name.trim().length > 0 const handleSave = () => { if (!nameValid(deckName)) { diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index 59e125bd..bef118c7 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -1,11 +1,19 @@ -import { useRouter } from 'next/router' +import React from "react" +import { useRouter } from "next/router" import Link from "next/link" + +interface QueryParamLinkProps { + children: React.ReactNode + href: string + className: string +} + /** * A Link component wrapper that appends a 'index' query parameter to the URL in development mode. * This is used to persist state across navigation during testing. */ -const QueryParamLink = ({ children, href, ...props }) => { +const QueryParamLink : React.FC = ({ children, href, ...props }) => { const router = useRouter() let url = href diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 5388d9eb..959f74a1 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -95,9 +95,9 @@ const ComponentWrapper = ({ // will ignore our existence and try to override us with their own account (depending on how // async code scheduling ends up working out). - // To carry the `index` query parameter to other parts of the app, be sure to either use: + // To carry the `index` query parameter to other parts of the app, be sure to either use: // - the `navigate` function from `utils/navigate.ts` instead of `router.push`. - // - the `link` component from `components/link.tsx` instead of `next/link` + // - the `link` component from `components/link.tsx` instead of `next/link` } return <> From f431eba29313b6278c2ed28e8da45c6908eaa677 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 01:30:21 +0100 Subject: [PATCH 27/52] extended FablePage type for the Collection Component props ot prevent warnings --- packages/webapp/src/pages/collection.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 189d3203..975b6789 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -27,7 +27,14 @@ const initialEffectMap = Object.assign({}, ...effects.map(name => ({[name]: fals const types = ['Creature', 'Magic', 'Weapon'] const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false}))) -const Collection: FablePage = ({ decks, setDecks, isHydrated }) => { +interface CollectionSpecificProps { + decks: Deck[] + setDecks: (decks: Deck[]) => void + isHydrated: boolean +} +type CollectionProps = FablePage & CollectionSpecificProps + +const Collection: React.FC = ({ decks, setDecks, isHydrated }) => { const router = useRouter() const { address } = useAccount() From c141bd07ac90f60a91b3e368ab69ecbce862fde0 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 19:37:12 +0100 Subject: [PATCH 28/52] decks stored in collection instead of _app --- packages/webapp/src/pages/_app.tsx | 5 +---- packages/webapp/src/pages/collection.tsx | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 959f74a1..6ba47bf4 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -77,9 +77,6 @@ const ComponentWrapper = ({ const isHydrated = useIsHydrated() const errorConfig = useErrorConfig() - // todo @eviterin: to be removed when these decks are put onchain with https://github.com/0xFableOrg/0xFable/issues/103 - const [decks, setDecks] = useState([]) - if (process.env.NODE_ENV === "development") { // constant // eslint-disable-next-line react-hooks/rules-of-hooks const router = useRouter() @@ -101,7 +98,7 @@ const ComponentWrapper = ({ } return <> - + {/* Global error modal for errors that don't have obvious in-flow resolutions. */} {isHydrated && errorConfig && } diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 975b6789..17bdc936 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -8,7 +8,7 @@ import jotaiDebug from "src/components/lib/jotaiDebug" import { Navbar } from "src/components/navbar" import { deployment } from "src/deployment" import { useInventoryCardsCollectionGetCollection } from "src/generated" -import { Card } from "src/store/types" +import { Deck, Card } from "src/store/types" import { Address } from "src/chain" import { FablePage } from "src/pages/_app" import { useRouter } from 'next/router' @@ -90,7 +90,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) setTypeMap({...typeMap, [type]: !typeMap[type]}) } - const handleDeckSelect = (deckID) => { + const handleDeckSelect = (deckID: number) => { const selectedDeck = decks[deckID] setCurrentDeck(selectedDeck) setEditingDeckIndex(deckID) From 3d2223bf1532809893de149d2998ea0adec2c204 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 19:38:56 +0100 Subject: [PATCH 29/52] use Deck type instead of card[] --- packages/webapp/src/pages/collection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 17bdc936..adf51195 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -50,7 +50,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) const [ editingDeckIndex, setEditingDeckIndex ] = useState(null) // Deck Construction Panel - const [ currentDeck, setCurrentDeck] = useState({ name: '', cards: [] }) + const [ currentDeck, setCurrentDeck] = useState(null) const [ selectedCards, setSelectedCards ] = useState([]) const activeEffects = Object.keys(effectMap).filter(key => effectMap[key]) From 99c3b1eb24f7f76f9e06fc01e57d95843e06f5b1 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 19:47:31 +0100 Subject: [PATCH 30/52] made explicit types --- packages/webapp/src/pages/collection.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index adf51195..780e7538 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -47,8 +47,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) const [ selectedCard, setSelectedCard ] = useState(null) // Deck Collection Display - const [ editingDeckIndex, setEditingDeckIndex ] = useState(null) - + const [ editingDeckIndex, setEditingDeckIndex ] = useState(null) // Deck Construction Panel const [ currentDeck, setCurrentDeck] = useState(null) const [ selectedCards, setSelectedCards ] = useState([]) @@ -98,7 +97,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) setSelectedCards(selectedDeck.cards) } - const handleSaveDeck = (updatedDeck) => { + const handleSaveDeck = (updatedDeck: Deck) => { const updatedDecks = [...decks] if (editingDeckIndex !== null) { // Update existing deck @@ -199,7 +198,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) {/* Right Panel - Deck List */}
- {isEditing ? ( + {isEditing && currentDeck ? ( Date: Tue, 30 Jan 2024 19:52:14 +0100 Subject: [PATCH 31/52] made sure the index param stays --- packages/webapp/src/components/collection/deckList.tsx | 2 +- packages/webapp/src/pages/collection.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/webapp/src/components/collection/deckList.tsx b/packages/webapp/src/components/collection/deckList.tsx index 3a0c1387..f8de4f8c 100644 --- a/packages/webapp/src/components/collection/deckList.tsx +++ b/packages/webapp/src/components/collection/deckList.tsx @@ -1,5 +1,5 @@ import React from 'react' -import Link from 'next/link' +import Link from "src/components/link" import { Deck } from 'src/store/types' interface DeckCollectionDisplayProps { diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 780e7538..ced3cc0d 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -12,12 +12,14 @@ import { Deck, Card } from "src/store/types" import { Address } from "src/chain" import { FablePage } from "src/pages/_app" import { useRouter } from 'next/router' +import { navigate } from "utils/navigate" import FilterPanel from 'src/components/collection/filterPanel' import CardCollectionDisplay from 'src/components/collection/cardCollectionDisplay' import DeckList from 'src/components/collection/deckList' import DeckPanel from 'src/components/collection/deckPanel' + // NOTE(norswap & geniusgarlic): Just an example, when the game actually has effects & types, // fetch those from the chain instead of hardcoding them here. type Effect = string @@ -109,13 +111,13 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) setDecks(updatedDecks) setIsEditing(false) setSelectedCards([]) - router.push('/collection') + navigate(router, '/collection') } const handleCancelEditing = () => { setIsEditing(false) setSelectedCards([]) - router.push('/collection') + navigate(router, '/collection') } const addToDeck = (card: Card) => { From 102fc6ddef3a83587a96f09632927c48113ad558 Mon Sep 17 00:00:00 2001 From: eviterin Date: Sun, 28 Jan 2024 20:38:30 +0100 Subject: [PATCH 32/52] corrected error message --- packages/webapp/src/actions/errors.ts | 2 +- packages/webapp/src/constants.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/actions/errors.ts b/packages/webapp/src/actions/errors.ts index 2492ccc9..e13284bc 100644 --- a/packages/webapp/src/actions/errors.ts +++ b/packages/webapp/src/actions/errors.ts @@ -178,7 +178,7 @@ export function defaultContractWriteErrorHandling(err: ContractWriteError): fals setError({ title: "Contract execution error", - message: `Transaction reverted (${err.args.functionName}) ${signatureMsg}.` + message: `Transaction reverted (${err.args.functionName}) ${signatureMsg}. ` + `Please report to ${GIT_ISSUES}`, buttons: [DISMISS_BUTTON] }) diff --git a/packages/webapp/src/constants.ts b/packages/webapp/src/constants.ts index 0b4307f8..d8cd289a 100644 --- a/packages/webapp/src/constants.ts +++ b/packages/webapp/src/constants.ts @@ -4,7 +4,7 @@ * @module constants */ -export const GIT_REPO = "https://github.com/norswap/0xFable" +export const GIT_REPO = "https://github.com/0xFableOrg/0xFable" export const GIT_ISSUES = `${GIT_REPO}/issues` /** Proof generation timeout (in seconds) for the proof of the initial hand. */ From 634a867375f4c127d22319edaaa9bc6c1e448f32 Mon Sep 17 00:00:00 2001 From: eviterin Date: Wed, 7 Feb 2024 17:13:00 +0100 Subject: [PATCH 33/52] add queryParamLink --- packages/webapp/src/components/link.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index bef118c7..58102b0d 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -1,19 +1,11 @@ -import React from "react" -import { useRouter } from "next/router" +import { useRouter } from 'next/router' import Link from "next/link" - -interface QueryParamLinkProps { - children: React.ReactNode - href: string - className: string -} - /** * A Link component wrapper that appends a 'index' query parameter to the URL in development mode. * This is used to persist state across navigation during testing. */ -const QueryParamLink : React.FC = ({ children, href, ...props }) => { +const QueryParamLink = ({ children, href, ...props }) => { const router = useRouter() let url = href @@ -24,7 +16,7 @@ const QueryParamLink : React.FC = ({ children, href, ...pro url = url + (url.includes("?") ? "&" : "?") + `index=${index}` } return ( - + {children} ) From f029ccd7d4f19d3f0c178c8361fc89c618b8df9e Mon Sep 17 00:00:00 2001 From: eviterin Date: Wed, 7 Feb 2024 16:29:46 +0100 Subject: [PATCH 34/52] remove extra import --- packages/webapp/src/components/link.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index 58102b0d..419b4908 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -1,11 +1,19 @@ -import { useRouter } from 'next/router' +import React from "react" +import { useRouter } from "next/router" import Link from "next/link" + +interface QueryParamLinkProps { + children: React.ReactNode + href: string + className: string +} + /** * A Link component wrapper that appends a 'index' query parameter to the URL in development mode. * This is used to persist state across navigation during testing. */ -const QueryParamLink = ({ children, href, ...props }) => { +const QueryParamLink : React.FC = ({ children, href, ...props }) => { const router = useRouter() let url = href From a270ef75ec69bd3b33fedb063d61c46623ceb66a Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 08:01:44 +0100 Subject: [PATCH 35/52] better card art selection --- .../src/components/collection/cardCollectionDisplay.tsx | 5 +++-- packages/webapp/src/components/collection/deckPanel.tsx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 3de58294..3515c624 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -2,6 +2,7 @@ import React from 'react' import Image from 'next/image' import { Card } from 'src/store/types' import { MintDeckModal } from 'src/components/modals/mintDeckModal' +import { testCards } from 'src/utils/card-list' interface CardCollectionDisplayProps { cards: Card[] @@ -24,7 +25,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is {isHydrated && cards.length > 0 && (
- {cards.map(card => ( + {cards.map((card, index) => (
= ({ cards, is } }} > - {card.lore.name} + tc.id === index)?.image || '/card_art/1.jpg'} alt={card.lore.name} width={256} height={256} />
{card.lore.name}
{card.stats.attack}
diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 8c411a8a..30f5ac0a 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react' import { Deck, Card } from 'src/store/types' import Image from 'next/image' +import { testCards } from 'src/utils/card-list' interface DeckConstructionPanelProps { deck: Deck @@ -70,8 +71,7 @@ interface DeckConstructionPanelProps { onClick={() => onCardSelect(card)} >
- {/* todo @eviterin: get proper link to the card instead of always the witch */} - Card art + tc.id === index)?.image || '/card_art/1.jpg'} alt ="Card art" width={40} height={40} className="object-cover rounded-full" /> {card.lore.name}
From 2661a57c6a4b0de2b5007bb8e618196206146527 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:14:14 +0100 Subject: [PATCH 36/52] Removed redundant comments --- .../src/components/collection/cardCollectionDisplay.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 3515c624..decf0aeb 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -29,12 +29,12 @@ const CardCollectionDisplay: React.FC = ({ cards, is
c.id === card.id) ? 'shadow-highlight shadow-orange-300' : '' // Highlight if selected + selectedCards.some(c => c.id === card.id) ? 'shadow-highlight shadow-orange-300' : '' } hover:bg-slate-800 rounded-lg p-4 border-4 border-slate-900 grow w-[220px] max-w-[330px]`} onMouseEnter={() => setSelectedCard(card)} onClick={() => { if (isEditing) { - onCardToggle(card) // Only toggle card selection when in editing mode + onCardToggle(card) } }} > From 70c942310335c58937875384857467b8121df9e5 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:25:06 +0100 Subject: [PATCH 37/52] deck names... --- .../webapp/src/components/collection/deckPanel.tsx | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 30f5ac0a..0bc236af 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -14,21 +14,18 @@ interface DeckConstructionPanelProps { const DeckConstructionPanel : React.FC = ({ deck, selectedCards = [], onCardSelect, onSave, onCancel }) => { const [ deckName, setDeckName ] = useState(deck.name) - const [ isDeckNameValid, setIsDeckNameValid ] = useState(true) + const [ deckNameValid, setIsDeckNameValid ] = useState(false) + + const nameValid = (name: string) => name.trim().length > 0 const handleDeckNameChange = (event: React.ChangeEvent) => { const newName = event.target.value setDeckName(event.target.value) setIsDeckNameValid(nameValid(newName)) } - - const nameValid = (name: string) => name.trim().length > 0 const handleSave = () => { - if (!nameValid(deckName)) { - setIsDeckNameValid(false) - return - } + if(!deckNameValid) return const newDeck = { name: deckName.trim(), @@ -46,7 +43,7 @@ interface DeckConstructionPanelProps { type="text" value={deckName} onChange={handleDeckNameChange} - style={{ outline: isDeckNameValid ? "none" : "2px solid red" }} + style={{ outline: deckNameValid ? "none" : "2px solid red" }} className="flex-grow px-2 py-2 border rounded-md text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent m-1.5" placeholder=" Deck name" /> From 7705e70fdc90aee3c6e4579186d373ae775859c2 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:37:05 +0100 Subject: [PATCH 38/52] Use our own button components and moved them down to their own row --- .../src/components/collection/deckPanel.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 0bc236af..10658d49 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react' import { Deck, Card } from 'src/store/types' import Image from 'next/image' import { testCards } from 'src/utils/card-list' +import { Button } from "src/components/ui/button" interface DeckConstructionPanelProps { deck: Deck @@ -47,17 +48,18 @@ interface DeckConstructionPanelProps { className="flex-grow px-2 py-2 border rounded-md text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent m-1.5" placeholder=" Deck name" /> - +
+ {/* Save and Cancel Buttons */}
- - + +
-
+ {/* List of Cards in the Deck */}
From aa8b57895c0652d1bd2f9cbb04175b037d7c16a1 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:39:09 +0100 Subject: [PATCH 39/52] flex the deck panel --- .../src/components/collection/deckPanel.tsx | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 10658d49..46380ec3 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -37,8 +37,8 @@ interface DeckConstructionPanelProps { } return ( -
-
+
+
{/* Deck Name Input */} -
- - {/* Save and Cancel Buttons */} -
- - -
+
+ {/* Save and Cancel Buttons */} +
+ + +
{/* List of Cards in the Deck */}
@@ -70,7 +69,7 @@ interface DeckConstructionPanelProps { onClick={() => onCardSelect(card)} >
- tc.id === index)?.image || '/card_art/1.jpg'} alt ="Card art" width={40} height={40} className="object-cover rounded-full" /> + tc.id === index)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> {card.lore.name}
From f859439e47ad9f8117dcff757ee0830cfc4f651d Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:46:22 +0100 Subject: [PATCH 40/52] made text readable by humans --- .../src/components/collection/deckPanel.tsx | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 46380ec3..ea9e3dd8 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -38,44 +38,44 @@ interface DeckConstructionPanelProps { return (
-
- {/* Deck Name Input */} - -
+
+ {/* Deck Name Input */} + +
- {/* Save and Cancel Buttons */} -
- - -
+ {/* Save and Cancel Buttons */} +
+ + +
- {/* List of Cards in the Deck */} -
- {selectedCards.map((card, index) => ( -
onCardSelect(card)} - > -
- tc.id === index)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> - {card.lore.name} -
+ {/* List of Cards in the Deck */} +
+ {selectedCards.map((card, index) => ( +
onCardSelect(card)} + > +
+ tc.id === index)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> + {card.lore.name}
- ))} -
+
+ ))}
+
) } From 9a8eaf92fb10e9a2758adc714587d0fc95d01f5c Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:52:17 +0100 Subject: [PATCH 41/52] use our own buttons --- .../src/components/collection/deckList.tsx | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/webapp/src/components/collection/deckList.tsx b/packages/webapp/src/components/collection/deckList.tsx index f8de4f8c..2f6171f2 100644 --- a/packages/webapp/src/components/collection/deckList.tsx +++ b/packages/webapp/src/components/collection/deckList.tsx @@ -1,6 +1,7 @@ import React from 'react' import Link from "src/components/link" import { Deck } from 'src/store/types' +import { Button } from "src/components/ui/button" interface DeckCollectionDisplayProps { decks: Deck[] @@ -11,21 +12,24 @@ const DeckCollectionDisplay: React.FC = ({ decks, on return (
{/* New Deck Button */} - - New Deck → - +
+ +
{/* Deck Buttons */} {decks.map((deck, deckID) => ( - + ))}
) From 345996f43707013b44b2973ed405fd537a8f6d77 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 20 Feb 2024 18:58:12 +0100 Subject: [PATCH 42/52] Made deck name buttons scale to daddy component width --- packages/webapp/src/components/collection/deckList.tsx | 2 +- packages/webapp/src/components/ui/button.tsx | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/webapp/src/components/collection/deckList.tsx b/packages/webapp/src/components/collection/deckList.tsx index 2f6171f2..abdcfb95 100644 --- a/packages/webapp/src/components/collection/deckList.tsx +++ b/packages/webapp/src/components/collection/deckList.tsx @@ -24,7 +24,7 @@ const DeckCollectionDisplay: React.FC = ({ decks, on {/* Deck Buttons */} {decks.map((deck, deckID) => ( - diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index ea9e3dd8..436275e9 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -62,10 +62,11 @@ interface DeckConstructionPanelProps { {/* List of Cards in the Deck */}
- {selectedCards.map((card, index) => ( + {selectedCards.length > 0 ? ( + selectedCards.map((card, index) => (
onCardSelect(card)} >
@@ -73,7 +74,12 @@ interface DeckConstructionPanelProps { {card.lore.name}
- ))} + )) + ) : ( +
+ Click on cards to add them to the deck. +
+ )}
) diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index 419b4908..90d026d6 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -6,14 +6,13 @@ import Link from "next/link" interface QueryParamLinkProps { children: React.ReactNode href: string - className: string } /** * A Link component wrapper that appends a 'index' query parameter to the URL in development mode. * This is used to persist state across navigation during testing. */ -const QueryParamLink : React.FC = ({ children, href, ...props }) => { +const QueryParamLink : React.FC = ({ children, href }) => { const router = useRouter() let url = href @@ -21,10 +20,10 @@ const QueryParamLink : React.FC = ({ children, href, ...pro if (process.env.NODE_ENV === "development") { const index = parseInt(router.query.index as string) if (index !== undefined && !isNaN(index) && 0 <= index && index <= 9) - url = url + (url.includes("?") ? "&" : "?") + `index=${index}` + url += (url.includes("?") ? "&" : "?") + `index=${index}` } return ( - + {children} ) From 661c69f8a076d3110b5f068cef18b1fd00c20fa2 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 23 Jan 2024 19:23:56 +0100 Subject: [PATCH 44/52] add .vs and .vscode to gitignore --- .gitignore | 2 ++ packages/webapp/.vs/slnx.sqlite | 0 packages/webapp/.vscode/settings.json | 4 ++++ packages/webapp/src/components/link.tsx | 1 - 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/webapp/.vs/slnx.sqlite create mode 100644 packages/webapp/.vscode/settings.json diff --git a/.gitignore b/.gitignore index b2d4a128..96cf9015 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # Environment variables *.env +.vscode +.vs # MacOS .DS_Store diff --git a/packages/webapp/.vs/slnx.sqlite b/packages/webapp/.vs/slnx.sqlite new file mode 100644 index 00000000..e69de29b diff --git a/packages/webapp/.vscode/settings.json b/packages/webapp/.vscode/settings.json new file mode 100644 index 00000000..255c9f62 --- /dev/null +++ b/packages/webapp/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "javascript.validate.enable": false, + "typescript.validate.enable": false +} \ No newline at end of file diff --git a/packages/webapp/src/components/link.tsx b/packages/webapp/src/components/link.tsx index 90d026d6..34f81147 100644 --- a/packages/webapp/src/components/link.tsx +++ b/packages/webapp/src/components/link.tsx @@ -2,7 +2,6 @@ import React from "react" import { useRouter } from "next/router" import Link from "next/link" - interface QueryParamLinkProps { children: React.ReactNode href: string From 1c06d682d615db2c96e96d4c97f4052c8adfa9d8 Mon Sep 17 00:00:00 2001 From: eviterin Date: Wed, 21 Feb 2024 19:28:31 +0100 Subject: [PATCH 45/52] removed fallback art for cards --- .../webapp/src/components/collection/cardCollectionDisplay.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index decf0aeb..bb74c719 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -38,7 +38,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is } }} > - tc.id === index)?.image || '/card_art/1.jpg'} alt={card.lore.name} width={256} height={256} /> + tc.id === index)?.image} alt={card.lore.name} width={256} height={256} />
{card.lore.name}
{card.stats.attack}
From 3a83806b1b689e2b876dd32ca10db579576c1bc0 Mon Sep 17 00:00:00 2001 From: eviterin Date: Thu, 22 Feb 2024 10:21:39 +0100 Subject: [PATCH 46/52] quick fix starting index is 1 --- .../webapp/src/components/collection/cardCollectionDisplay.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index bb74c719..89aa41c5 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -38,7 +38,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is } }} > - tc.id === index)?.image} alt={card.lore.name} width={256} height={256} /> + tc.id === index + 1)?.image} alt={card.lore.name} width={256} height={256} />
{card.lore.name}
{card.stats.attack}
From 36e35aed807788202a4c1eeb255fafa4866c7827 Mon Sep 17 00:00:00 2001 From: eviterin Date: Thu, 22 Feb 2024 10:46:24 +0100 Subject: [PATCH 47/52] Improved flexing the deck panel --- .../src/components/collection/deckPanel.tsx | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index 436275e9..e279500a 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -37,51 +37,51 @@ interface DeckConstructionPanelProps { } return ( -
-
+
{/* Deck Name Input */} - -
+
+ +
- {/* Save and Cancel Buttons */} -
- - -
+ {/* Save and Cancel Buttons */} +
+ + +
- {/* List of Cards in the Deck */} -
- {selectedCards.length > 0 ? ( - selectedCards.map((card, index) => ( -
onCardSelect(card)} - > -
- tc.id === index)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> - {card.lore.name} + {/* List of Cards in the Deck */} +
+ {selectedCards.length > 0 ? ( + selectedCards.map((card, index) => ( +
onCardSelect(card)} + > +
+ tc.id === card.id)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> + {card.lore.name} +
+ )) + ) : ( +
+ Click on cards to add them to the deck.
- )) - ) : ( -
- Click on cards to add them to the deck. + )}
- )}
-
) } From 42f25f760738057fc2a7bbb89e7ba7b003f6f7d5 Mon Sep 17 00:00:00 2001 From: eviterin Date: Mon, 26 Feb 2024 09:40:53 +0100 Subject: [PATCH 48/52] Fix bug where deck was not editable --- packages/webapp/src/components/collection/deckPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index e279500a..a95fa324 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -26,7 +26,7 @@ interface DeckConstructionPanelProps { } const handleSave = () => { - if(!deckNameValid) return + if(!nameValid(deckName)) return const newDeck = { name: deckName.trim(), From 928aded81ea57ac9d4dbf4ff5b0d020b7e9e4d71 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Norswap\" Laurent" Date: Tue, 27 Feb 2024 03:17:27 -0700 Subject: [PATCH 49/52] make check --- .../src/components/collection/cardCollectionDisplay.tsx | 2 +- packages/webapp/src/pages/_app.tsx | 2 +- packages/webapp/src/pages/collection.tsx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx index 89aa41c5..912c8fbf 100644 --- a/packages/webapp/src/components/collection/cardCollectionDisplay.tsx +++ b/packages/webapp/src/components/collection/cardCollectionDisplay.tsx @@ -38,7 +38,7 @@ const CardCollectionDisplay: React.FC = ({ cards, is } }} > - tc.id === index + 1)?.image} alt={card.lore.name} width={256} height={256} /> + Number(tc.id) === index + 1)?.image || ""} alt={card.lore.name} width={256} height={256} />
{card.lore.name}
{card.stats.attack}
diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 6ba47bf4..c06a4c95 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -9,7 +9,7 @@ import { NextPage } from "next" import type { AppType } from "next/app" import Head from "next/head" import { useAccount, WagmiConfig } from "wagmi" -import { Dispatch, SetStateAction, useState } from "react" +import { Dispatch, SetStateAction } from "react" import { ensureLocalAccountIndex, wagmiConfig } from "src/chain" import jotaiDebug from "src/components/lib/jotaiDebug" import { GlobalErrorModal } from "src/components/modals/globalErrorModal" diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index ced3cc0d..6b128245 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -1,7 +1,7 @@ import debounce from "lodash/debounce" import Head from "next/head" -import { useState, useMemo, useEffect } from "react" +import React, { useState, useMemo, useEffect } from "react" import { useAccount } from "wagmi" import jotaiDebug from "src/components/lib/jotaiDebug" @@ -111,13 +111,13 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) setDecks(updatedDecks) setIsEditing(false) setSelectedCards([]) - navigate(router, '/collection') + void navigate(router, '/collection') } const handleCancelEditing = () => { setIsEditing(false) setSelectedCards([]) - navigate(router, '/collection') + void navigate(router, '/collection') } const addToDeck = (card: Card) => { From 60aff3f36f1a8674f5d0a3d092c2fc7e7a827ccd Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 27 Feb 2024 17:04:57 +0100 Subject: [PATCH 50/52] Deck display no longer crashes if the player does not own any decks --- packages/webapp/src/pages/collection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 6b128245..08e781cc 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -210,7 +210,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) /> ) : ( )} From 3cf1f440ea4250ed11ef933b7b1b68fd40ec0557 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 27 Feb 2024 17:19:05 +0100 Subject: [PATCH 51/52] Removed unnessecarily complex props from collection and resolved a bug when saving an existing deck --- .../webapp/src/components/collection/deckPanel.tsx | 2 +- packages/webapp/src/pages/_app.tsx | 2 +- packages/webapp/src/pages/collection.tsx | 13 ++++--------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/webapp/src/components/collection/deckPanel.tsx b/packages/webapp/src/components/collection/deckPanel.tsx index a95fa324..f9faeac1 100644 --- a/packages/webapp/src/components/collection/deckPanel.tsx +++ b/packages/webapp/src/components/collection/deckPanel.tsx @@ -70,7 +70,7 @@ interface DeckConstructionPanelProps { onClick={() => onCardSelect(card)} >
- tc.id === card.id)?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> + tc.id === Number(card.id))?.image || '/card_art/1.jpg'} alt="Card art" width={40} height={40} className="object-cover rounded-full" /> {card.lore.name}
diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index c06a4c95..746fc88e 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -28,7 +28,7 @@ import { Toaster } from "src/components/ui/sonner" * Make pages in the app conform to this type. * See [@link useIsHydrated] for more info on the meaning of the `isHydrated` prop. */ -export type FablePage = NextPage<{ decks: Deck[], isHydrated: boolean, setDecks: Dispatch> }> +export type FablePage = NextPage<{ isHydrated: boolean }> // ================================================================================================= diff --git a/packages/webapp/src/pages/collection.tsx b/packages/webapp/src/pages/collection.tsx index 08e781cc..e9463bf7 100644 --- a/packages/webapp/src/pages/collection.tsx +++ b/packages/webapp/src/pages/collection.tsx @@ -29,14 +29,7 @@ const initialEffectMap = Object.assign({}, ...effects.map(name => ({[name]: fals const types = ['Creature', 'Magic', 'Weapon'] const initialTypeMap = Object.assign({}, ...types.map(name => ({[name]: false}))) -interface CollectionSpecificProps { - decks: Deck[] - setDecks: (decks: Deck[]) => void - isHydrated: boolean -} -type CollectionProps = FablePage & CollectionSpecificProps - -const Collection: React.FC = ({ decks, setDecks, isHydrated }) => { +const Collection: FablePage = ({ isHydrated }) => { const router = useRouter() const { address } = useAccount() @@ -50,6 +43,8 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) // Deck Collection Display const [ editingDeckIndex, setEditingDeckIndex ] = useState(null) + const [decks, setDecks] = useState([]) + // Deck Construction Panel const [ currentDeck, setCurrentDeck] = useState(null) const [ selectedCards, setSelectedCards ] = useState([]) @@ -100,7 +95,7 @@ const Collection: React.FC = ({ decks, setDecks, isHydrated }) } const handleSaveDeck = (updatedDeck: Deck) => { - const updatedDecks = [...decks] + const updatedDecks = [...(decks || [])] if (editingDeckIndex !== null) { // Update existing deck updatedDecks[editingDeckIndex] = updatedDeck From 0f1f0aa7401c3af785cd4e4bf14698334bf9ff56 Mon Sep 17 00:00:00 2001 From: eviterin Date: Tue, 27 Feb 2024 17:20:34 +0100 Subject: [PATCH 52/52] Removed unused imports --- packages/webapp/src/pages/_app.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/webapp/src/pages/_app.tsx b/packages/webapp/src/pages/_app.tsx index 746fc88e..c5388cbe 100644 --- a/packages/webapp/src/pages/_app.tsx +++ b/packages/webapp/src/pages/_app.tsx @@ -3,23 +3,19 @@ // Must come first, so that can we can hook global members before they're used by imports. import "src/setup" import "src/store/setup" - import { ConnectKitProvider } from "connectkit" import { NextPage } from "next" import type { AppType } from "next/app" import Head from "next/head" import { useAccount, WagmiConfig } from "wagmi" -import { Dispatch, SetStateAction } from "react" import { ensureLocalAccountIndex, wagmiConfig } from "src/chain" import jotaiDebug from "src/components/lib/jotaiDebug" import { GlobalErrorModal } from "src/components/modals/globalErrorModal" import { useIsHydrated } from "src/hooks/useIsHydrated" import { useErrorConfig } from "src/store/hooks" - import "src/styles/globals.css" import { useRouter } from "next/router" import { ComponentType, useEffect } from "react" -import { Deck } from "src/store/types" import { Toaster } from "src/components/ui/sonner" // =================================================================================================