@@ -61,16 +61,11 @@ const CryptoKitties: React.FC<{
6161 sire : Contract < AbiFragment [ ] > ,
6262} > = ( { walletAddress, dapperWalletAddress, invokeTx, core, sale, sire } ) => {
6363
64- const initFormState : FormDetails = {
65- kittyId : '' ,
66- loading : false ,
67- }
68-
6964 // Component state
7065 const [ kittyStatuses , setKittyStatuses ] = useState < KittyStatus [ ] > ( [ ] ) // Status for multiple kitties
7166 const [ balance , setBalance ] = useState < number > ( 0 ) // User's CryptoKitties balance
7267 const [ totalSupply , setTotalSupply ] = useState < number > ( 0 ) // Total number of CryptoKitties
73- const [ formDetails , setFormDetails ] = useState < FormDetails > ( initFormState ) // Form state
68+ const [ kittyId , setKittyId ] = useState ( '' ) // Input value
7469
7570 useEffect ( ( ) => {
7671 const init = async ( ) => {
@@ -119,23 +114,22 @@ const CryptoKitties: React.FC<{
119114 * @throws {Error } If auction cancellation fails
120115 */
121116 const handleCancelAuction = async ( isSaleAuction : boolean , tokenId : string ) => {
122- setFormDetails ( prevState => ( { ...prevState , loading : true } ) )
117+ setKittyStatuses ( prev => prev . map ( s =>
118+ s . id === tokenId ? { ...s , loading : true } : s
119+ ) ) ;
123120 const contract = isSaleAuction ? sale : sire
124121 const address = isSaleAuction ? Contracts [ 'Sale' ] . addr : Contracts [ 'Sire' ] . addr
125122 const methodCall = contract . methods . cancelAuction ( tokenId )
126123 try {
127124 await invokeTx ( address , methodCall , '0' )
128125 setKittyStatuses ( prev => prev . map ( s =>
129- s . id === tokenId ? { ...s , auctionCancelled : true } : s
126+ s . id === tokenId ? { ...s , auctionCancelled : true , loading : false } : s
130127 ) ) ;
131128 } catch ( e ) {
132129 const errorMessage = 'Failed to cancel auction. Please try again.' ;
133- alert ( errorMessage ) ;
134130 setKittyStatuses ( prev => prev . map ( s =>
135- s . id === tokenId ? { ...s , error : errorMessage } : s
131+ s . id === tokenId ? { ...s , error : errorMessage , loading : false } : s
136132 ) ) ;
137- } finally {
138- setFormDetails ( prevState => ( { ...prevState , loading : false } ) )
139133 }
140134 }
141135
@@ -147,22 +141,21 @@ const CryptoKitties: React.FC<{
147141 * @throws {Error } If transfer fails
148142 */
149143 const handleTransfer = async ( kittyId : string ) => {
150- setFormDetails ( prevState => ( { ...prevState , loading : true } ) )
144+ setKittyStatuses ( prev => prev . map ( s =>
145+ s . id === kittyId ? { ...s , loading : true } : s
146+ ) ) ;
151147 const address = Contracts [ 'Core' ] . addr
152148 const methodCall = core . methods . transfer ( walletAddress , kittyId )
153149 try {
154150 await invokeTx ( address , methodCall , '0' )
155151 setKittyStatuses ( prev => prev . map ( s =>
156- s . id === kittyId ? { ...s , transferSuccess : true } : s
152+ s . id === kittyId ? { ...s , transferSuccess : true , loading : false } : s
157153 ) )
158154 } catch ( e ) {
159155 const errorMessage = 'Failed to transfer. Please try again.' ;
160- alert ( errorMessage ) ;
161156 setKittyStatuses ( prev => prev . map ( s =>
162- s . id === kittyId ? { ...s , error : errorMessage } : s
157+ s . id === kittyId ? { ...s , error : errorMessage , loading : false } : s
163158 ) ) ;
164- } finally {
165- setFormDetails ( prevState => ( { ...prevState , loading : false } ) )
166159 }
167160 }
168161
@@ -171,30 +164,26 @@ const CryptoKitties: React.FC<{
171164 * @param {React.ChangeEvent<HTMLInputElement> } e - Change event
172165 * @param {keyof FormDetails } changeParam - Form field to update
173166 */
174- const handleChange = ( e : React . ChangeEvent < HTMLInputElement > , changeParam : keyof FormDetails ) => {
175- const { value } = e . target
176- const newState = { ...formDetails }
177- if ( changeParam === 'kittyId' ) {
178- newState . kittyId = value
167+ const handleChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
168+ const value = e . target . value ;
169+ setKittyId ( value ) ;
179170
180- // Clear existing statuses when input changes
181- setKittyStatuses ( [ ] )
171+ // Clear existing statuses when input changes
172+ setKittyStatuses ( [ ] ) ;
182173
183- // Show all IDs immediately
184- const ids = value . split ( ',' )
185- . map ( id => id . trim ( ) )
186- . filter ( id => id !== '' ) ;
174+ // Show all IDs immediately
175+ const ids = value . split ( ',' )
176+ . map ( id => id . trim ( ) )
177+ . filter ( id => id !== '' ) ;
187178
188- setKittyStatuses ( ids . map ( id => ( {
189- id,
190- transferrable : false ,
191- forSale : false ,
192- forSire : false ,
193- loading : false ,
194- error : ! isValidKittyId ( id ) ? 'Invalid kitty ID' : undefined
195- } ) ) ) ;
196- }
197- setFormDetails ( newState )
179+ setKittyStatuses ( ids . map ( id => ( {
180+ id,
181+ transferrable : false ,
182+ forSale : false ,
183+ forSire : false ,
184+ loading : false ,
185+ error : ! isValidKittyId ( id ) ? 'Invalid kitty ID' : undefined
186+ } ) ) ) ;
198187 }
199188
200189 /**
@@ -205,46 +194,69 @@ const CryptoKitties: React.FC<{
205194 const checkAllKitties = async ( ) => {
206195 // Get valid IDs
207196 const ids = kittyStatuses
208- . filter ( status => ! status . error )
197+ . filter ( status => ! status . error || (
198+ status . error !== 'Invalid kitty ID'
199+ ) )
209200 . map ( status => status . id ) ;
201+
202+ // Create a copy of current statuses to update
203+ let updatedStatuses = [ ...kittyStatuses ] ;
204+
210205 for ( let i = 0 ; i < ids . length ; i ++ ) {
211206 const kittyId = ids [ i ] ;
212- setKittyStatuses ( prev => prev . map ( status =>
213- status . id === kittyId ? { ...status , loading : true , error : undefined } : status
214- ) ) ;
207+
208+ // Update loading state for current kitty
209+ updatedStatuses = updatedStatuses . map ( status =>
210+ status . id === kittyId ? {
211+ id : status . id ,
212+ transferrable : false ,
213+ forSale : false ,
214+ forSire : false ,
215+ loading : true ,
216+ error : undefined ,
217+ transferSuccess : undefined ,
218+ auctionCancelled : undefined
219+ } : status
220+ ) ;
221+ setKittyStatuses ( updatedStatuses ) ;
215222
216223 try {
217224 const owner = await core . methods . ownerOf ( kittyId ) . call ( ) ;
218225 if ( owner && owner . toString ( ) . toLowerCase ( ) === dapperWalletAddress . toLowerCase ( ) ) {
219- setKittyStatuses ( prev => prev . map ( status =>
226+ updatedStatuses = updatedStatuses . map ( status =>
220227 status . id === kittyId ? { ...status , transferrable : true , loading : false } : status
221- ) ) ;
228+ ) ;
229+ setKittyStatuses ( updatedStatuses ) ;
222230 continue ;
223231 }
224232
225233 const isInSaleAuction = await checkAuction ( sale , kittyId ) ;
226234
227235 if ( isInSaleAuction ) {
228- setKittyStatuses ( prev => prev . map ( status =>
236+ updatedStatuses = updatedStatuses . map ( status =>
229237 status . id === kittyId ? { ...status , forSale : true , loading : false } : status
230- ) ) ;
238+ ) ;
239+ setKittyStatuses ( updatedStatuses ) ;
231240 } else {
232241 const isInSireAuction = await checkAuction ( sire , kittyId ) ;
233242 if ( isInSireAuction ) {
234- setKittyStatuses ( prev => prev . map ( status =>
243+ updatedStatuses = updatedStatuses . map ( status =>
235244 status . id === kittyId ? { ...status , forSire : true , loading : false } : status
236- ) ) ;
245+ ) ;
246+ setKittyStatuses ( updatedStatuses ) ;
237247 } else {
238- setKittyStatuses ( prev => prev . map ( status =>
248+ updatedStatuses = updatedStatuses . map ( status =>
239249 status . id === kittyId ? { ...status , loading : false , error : 'Not owned by this Dapper Wallet' } : status
240- ) ) ;
250+ ) ;
251+ setKittyStatuses ( updatedStatuses ) ;
241252 }
242253 }
243254 } catch ( error ) {
244255 const errorMessage = 'An error occurred while checking ownership.' ;
245- setKittyStatuses ( prev => prev . map ( status =>
256+ updatedStatuses = updatedStatuses . map ( status =>
246257 status . id === kittyId ? { ...status , loading : false , error : errorMessage } : status
247- ) ) ;
258+ ) ;
259+ setKittyStatuses ( updatedStatuses ) ;
248260 }
249261 }
250262 }
@@ -271,15 +283,14 @@ const CryptoKitties: React.FC<{
271283 < input
272284 id = { 'tokenIds' }
273285 type = { 'text' }
274- value = { formDetails . kittyId }
275- onChange = { e => handleChange ( e , 'kittyId' ) }
276- disabled = { formDetails . loading }
286+ value = { kittyId }
287+ onChange = { handleChange }
277288 placeholder = "Example: 123 or 123,456,789"
278289 />
279290 </ label >
280291 < button
281292 onClick = { checkAllKitties }
282- disabled = { formDetails . loading }
293+ disabled = { kittyStatuses . some ( status => status . loading ) }
283294 >
284295 { 'Check Kitties' }
285296 </ button >
@@ -303,15 +314,15 @@ const CryptoKitties: React.FC<{
303314 { status . transferrable && (
304315 < button
305316 onClick = { async ( ) => await handleTransfer ( status . id ) }
306- disabled = { formDetails . loading }
317+ disabled = { status . loading }
307318 >
308319 Transfer Kitty
309320 </ button >
310321 ) }
311322 { ( status . forSale || status . forSire ) && (
312323 < button
313324 onClick = { async ( ) => await handleCancelAuction ( status . forSale , status . id ) }
314- disabled = { formDetails . loading }
325+ disabled = { status . loading }
315326 >
316327 { `Cancel ${ status . forSale ? 'Sale' : 'Sire' } Auction` }
317328 </ button >
0 commit comments