Skip to content

[TASK-8898] feat: multi-device request links history#691

Merged
jjramirezn merged 3 commits intopeanut-wallet-devfrom
feat/requests-in-history
Feb 19, 2025
Merged

[TASK-8898] feat: multi-device request links history#691
jjramirezn merged 3 commits intopeanut-wallet-devfrom
feat/requests-in-history

Conversation

@jjramirezn
Copy link
Copy Markdown
Contributor

@jjramirezn jjramirezn commented Feb 17, 2025

contributes to TASK-8277

Summary by CodeRabbit

  • Refactor

    • Improved data fetching and state management for the history dashboard to enhance stability and prevent potential stale updates.
    • Updated transaction identifier generation by incorporating date information for improved uniqueness.
    • Streamlined the handling of dashboard data by removing unused functions related to request links.
    • Simplified the Dashboard component's logic by adopting asynchronous data handling.
  • Chores

    • Removed link deletion capability and streamlined request processing by eliminating redundant local storage operations.
    • Removed local storage management for request links and their fulfillments across multiple components.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 17, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
peanut-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Feb 18, 2025 2:35pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 17, 2025

Walkthrough

This pull request modifies several components to remove local storage management for request links. In the HistoryPage and Dashboard hook, the data fetching process is now asynchronous and includes updated identifier generation. The link deletion functionality and associated utility functions for saving or retrieving request links and their fulfillments have been removed from various request components and utility files.

Changes

Files Change Summary
src/app/(mobile-ui)/history/page.tsx Modified dashboard data fetching to use an asynchronous call, updated ID generation logic, and removed the handleDeleteLink function.
src/components/Dashboard/useDashboard.tsx Removed peanut-related request link processing and the removeRequestLinkFromLocalStorage function; updated composeLinkDataArray to fetch data via a history API call.
src/components/Request/{Create/Views/Initial.view.tsx, Pay/Views/Initial.view.tsx, Pay/Views/Success.view.tsx} Removed imports and calls to local storage functions for both request link creation and fulfillment, simplifying related UI logic.
src/utils/general.utils.ts Deleted multiple utility functions related to saving, retrieving, and updating request link and fulfillment data in local storage.

Sequence Diagram(s)

sequenceDiagram
    participant HP as HistoryPage
    participant UD as useDashboard Hook
    participant API as History API
    HP->>UD: Trigger useEffect on mount
    UD->>API: Call composeLinkDataArray(address) asynchronously
    API-->>UD: Return dashboard data
    UD-->>HP: Update dashboard state (if component still mounted)
Loading

Possibly related PRs

  • Disable sorting #468: The changes in this PR are related to the removal of the removeRequestLinkFromLocalStorage function, which is also removed in the retrieved PR, indicating a shared focus on eliminating local storage management for request links.
  • Release #456: The changes in this PR are related to the removal of the removeRequestLinkFromLocalStorage function, which is also removed in the retrieved PR's useDashboard hook, indicating a direct connection in the handling of link management.
  • [TASK-7301] Sync main into develop #553: The changes in this PR, specifically the removal of the removeRequestLinkFromLocalStorage function and modifications to the composeLinkDataArray function, are related to the changes in the retrieved PR, which also involves the removal of local storage functions and updates to the handling of link data.

Poem

Oh, what a hop we’ve made in code,
Banishing old links down the road.
No more clutters in local store,
Async flows now help us soar.
With each new line, my heart does leap—🐰
A bunny’s cheer for clean code to keep!
Hop on!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@notion-workspace
Copy link
Copy Markdown

@notion-workspace
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (2)
src/components/Request/Create/Views/Initial.view.tsx (2)

131-140: 🛠️ Refactor suggestion

Improve link generation logic.

The current link generation has several areas for improvement:

  1. Manual string concatenation is error-prone
  2. Parameters are not URL encoded
  3. TODOs indicate need for better structure

Consider creating a utility function like this:

function generateRequestLink(details: {
  recipientAddress: string,
  tokenAmount?: string,
  tokenSymbol?: string,
  uuid: string
}): string {
  const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
  const path = `/${encodeURIComponent(details.recipientAddress)}`;
  const params = new URLSearchParams();
  
  if (details.tokenAmount) path += `/${encodeURIComponent(details.tokenAmount)}`;
  if (details.tokenSymbol) path += `/${encodeURIComponent(details.tokenSymbol)}`;
  params.append('id', details.uuid);
  
  return `${baseUrl}${path}?${params.toString()}`;
}

174-203: 🛠️ Refactor suggestion

Remove setTimeout and add cleanup for useEffect.

Using setTimeout for state updates is an anti-pattern that could lead to race conditions. Consider:

  1. Removing the artificial delay
  2. Adding cleanup function

Apply this change:

 useEffect(() => {
     if (!isConnected) {
         setRecipientAddress('')
         setIsValidRecipient(false)
         return
     }

     // reset recipient when wallet type changes or when selected wallet changes
     if (address) {
         // reset states first
         setRecipientAddress('')
         setIsValidRecipient(false)

-        // set recipient to connected wallet address with a delay
-        setTimeout(() => {
-            setRecipientAddress(address)
-            setIsValidRecipient(true)
-        }, 100)
+        // set recipient to connected wallet address
+        setRecipientAddress(address)
+        setIsValidRecipient(true)

         // set chain and token for Peanut Wallet
         if (isPeanutWallet) {
             setSelectedChainID(PEANUT_WALLET_CHAIN.id.toString())
             setSelectedTokenAddress(PEANUT_WALLET_TOKEN)
         } else {
             // set chain and token for external wallet
             setSelectedChainID(selectedChainID)
             setSelectedTokenAddress(selectedTokenAddress)
         }
     }
+    
+    return () => {
+        // Cleanup function to prevent state updates on unmounted component
+        setRecipientAddress('')
+        setIsValidRecipient(false)
+    }
 }, [isConnected, isPeanutWallet, address])
🧹 Nitpick comments (5)
src/components/Request/Pay/Views/Initial.view.tsx (3)

58-58: Consider moving the Squid Router URL to configuration.

Hardcoding external service URLs makes it difficult to switch environments or handle service outages. Consider moving this URL to an environment configuration file.

-        squidRouterUrl: 'https://apiplus.squidrouter.com/v2/route',
+        squidRouterUrl: config.SQUID_ROUTER_URL,

99-102: Consider defining error state type.

Define a type for the error state object to improve type safety and maintainability.

+interface ErrorState {
+    showError: boolean;
+    errorMessage: string;
+}

-    const [errorState, setErrorState] = useState<{
-        showError: boolean
-        errorMessage: string
-    }>({ showError: false, errorMessage: '' })
+    const [errorState, setErrorState] = useState<ErrorState>({ showError: false, errorMessage: '' })

523-546: Track points estimation implementation.

The TODO comment for points estimation should be tracked in the issue system for proper follow-up.

Would you like me to create an issue to track the implementation of the points estimation feature? I can help draft the issue with the requirements and implementation details.

src/components/Request/Create/Views/Initial.view.tsx (1)

146-154: Enhance error handling.

The current error handling uses a generic message and only logs details to console. Consider:

  1. Providing specific error messages based on error type
  2. Adding retry mechanism for network failures
  3. Implementing proper error tracking

Example implementation:

} catch (error) {
  let errorMessage = 'Failed to create link';
  if (error instanceof TypeError) {
    errorMessage = 'Network error. Please try again.';
  } else if (error instanceof Response) {
    errorMessage = `Server error: ${await error.text()}`;
  }
  
  setErrorState({
    showError: true,
    errorMessage
  });
  
  // Consider adding error tracking
  console.error('Failed to create link:', error);
  
  // Optional: Implement retry for network errors
  if (error instanceof TypeError && retryCount < MAX_RETRIES) {
    setTimeout(() => handleOnNext({...params, retryCount: (retryCount || 0) + 1}), RETRY_DELAY);
    return;
  }
} finally {
src/components/Dashboard/useDashboard.tsx (1)

219-223: Remove unused parameter.

The _itemsPerPage parameter is not used in the function. Consider removing it if it's no longer needed.

 const filterDashboardData = (
     filterValue: string,
-    dashboardData: interfaces.IDashboardItem[],
-    _itemsPerPage: number
+    dashboardData: interfaces.IDashboardItem[]
 ) => {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b3966e and c5d2bae.

📒 Files selected for processing (6)
  • src/app/(mobile-ui)/history/page.tsx (2 hunks)
  • src/components/Dashboard/useDashboard.tsx (6 hunks)
  • src/components/Request/Create/Views/Initial.view.tsx (1 hunks)
  • src/components/Request/Pay/Views/Initial.view.tsx (1 hunks)
  • src/components/Request/Pay/Views/Success.view.tsx (0 hunks)
  • src/utils/general.utils.ts (0 hunks)
💤 Files with no reviewable changes (2)
  • src/components/Request/Pay/Views/Success.view.tsx
  • src/utils/general.utils.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (6)
src/components/Request/Pay/Views/Initial.view.tsx (2)

29-29: LGTM! Import changes align with PR objectives.

The removal of the saveRequestLinkFulfillmentToLocalStorage import aligns with the PR's goal of removing local storage management for request links.


416-575: LGTM! Well-structured UI implementation.

The UI implementation is clean and well-organized with:

  • Clear conditional rendering for different wallet types
  • Appropriate error message display
  • Well-presented network cost and slippage information
src/components/Request/Create/Views/Initial.view.tsx (2)

14-14: LGTM! Removal of local storage management.

The removal of local storage utilities aligns with the PR objectives to eliminate local storage management for request links.


205-284: LGTM! Clean and well-structured render logic.

The component's render logic is well-organized with:

  • Clear component hierarchy
  • Proper conditional rendering
  • Good error state handling
src/app/(mobile-ui)/history/page.tsx (2)

24-24: LGTM! Good implementation of async data fetching.

The stale check pattern is well-implemented to prevent memory leaks during component unmount.

Also applies to: 28-37


50-50: LGTM! Improved id generation.

The new id format ${data.link ?? ''}-${data.txHash ?? ''}-${data.date} provides better uniqueness by including the date.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
src/components/Dashboard/index.tsx (1)

185-185: ⚠️ Potential issue

Replace Math.random() in keys with stable identifiers.

Using Math.random() for React keys is an anti-pattern that can cause unnecessary re-renders and performance issues. Use a stable, unique identifier instead.

-                                                key={(link.link ?? link.txHash ?? '') + Math.random()}
+                                                key={link.link ?? link.txHash ?? `${link.date}-${link.amount}-${link.type}`}
-                                    <div key={(link.link ?? link.txHash ?? '') + Math.random()}>
+                                    <div key={link.link ?? link.txHash ?? `${link.date}-${link.amount}-${link.type}`}>

Also applies to: 235-235

🧹 Nitpick comments (2)
src/components/Dashboard/index.tsx (2)

52-69: Optimize legacy link handling.

The legacy link handling logic is nested within the promise chain, which could delay the UI update. Consider extracting this logic to a separate effect or function.

Extract the legacy link handling:

+    const getLegacyLinks = (address: string) => {
+        const links: string[] = []
+        const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address })
+        if (legacyLinkObject) {
+            legacyLinkObject.forEach((obj) => {
+                links.push(obj.link)
+            })
+        }
+        const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address })
+        if (raffleLegacyLinkObject) {
+            raffleLegacyLinkObject.forEach((obj) => {
+                links.push(obj.link)
+            })
+        }
+        return links
+    }

     useEffect(() => {
         let stale = false
 
         composeLinkDataArray(address ?? '').then((linkData) => {
             if (stale) return
             setTotalPages(Math.ceil(linkData.length / itemsPerPage))
             setCurrentPage(1)
             setDashboardData(/* ... */)
-            if (address) {
-                const links: string[] = []
-                const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
-                // ... legacy link handling
-                setLegacyLinks(links)
-            } else {
-                setLegacyLinks([])
-            }
         })
 
         return () => {
             stale = true
         }
     }, [address])
+
+    useEffect(() => {
+        setLegacyLinks(address ? getLegacyLinks(address) : [])
+    }, [address])

101-101: Remove commented code.

Remove the commented out dependency array as it's no longer needed and could cause confusion.

-        // }, [currentPage, dashboardData])
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c5d2bae and 250c197.

📒 Files selected for processing (1)
  • src/components/Dashboard/index.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview

Comment on lines 34 to +70
useEffect(() => {
const linkData = composeLinkDataArray(address ?? '')
setTotalPages(Math.ceil(linkData.length / itemsPerPage))
setCurrentPage(1)
setDashboardData(
linkData.sort((a, b) => {
const dateA = new Date(a.date).getTime()
const dateB = new Date(b.date).getTime()
if (dateA === dateB) {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else {
return dateB - dateA
}
})
)
let stale = false

if (address) {
const links: string[] = []
const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
if (legacyLinkObject) {
legacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address: address })
if (raffleLegacyLinkObject) {
raffleLegacyLinkObject.forEach((obj) => {
links.push(obj.link)
composeLinkDataArray(address ?? '').then((linkData) => {
if (stale) return
setTotalPages(Math.ceil(linkData.length / itemsPerPage))
setCurrentPage(1)
setDashboardData(
linkData.sort((a, b) => {
const dateA = new Date(a.date).getTime()
const dateB = new Date(b.date).getTime()
if (dateA === dateB) {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else {
return dateB - dateA
}
})
)
if (address) {
const links: string[] = []
const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
if (legacyLinkObject) {
legacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address: address })
if (raffleLegacyLinkObject) {
raffleLegacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
setLegacyLinks(links)
} else {
setLegacyLinks([])
}
setLegacyLinks(links)
} else {
setLegacyLinks([])
})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for the async operation.

The async operation lacks error handling, which could lead to unhandled promise rejections and a poor user experience if the data fetching fails.

Add error handling:

-        composeLinkDataArray(address ?? '').then((linkData) => {
+        composeLinkDataArray(address ?? '').then((linkData) => {
             if (stale) return
             setTotalPages(Math.ceil(linkData.length / itemsPerPage))
             // ... rest of the code
-        })
+        }).catch((error) => {
+            if (stale) return
+            console.error('Failed to fetch link data:', error)
+            // Consider adding user feedback for the error state
+        })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
const linkData = composeLinkDataArray(address ?? '')
setTotalPages(Math.ceil(linkData.length / itemsPerPage))
setCurrentPage(1)
setDashboardData(
linkData.sort((a, b) => {
const dateA = new Date(a.date).getTime()
const dateB = new Date(b.date).getTime()
if (dateA === dateB) {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else {
return dateB - dateA
}
})
)
let stale = false
if (address) {
const links: string[] = []
const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
if (legacyLinkObject) {
legacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address: address })
if (raffleLegacyLinkObject) {
raffleLegacyLinkObject.forEach((obj) => {
links.push(obj.link)
composeLinkDataArray(address ?? '').then((linkData) => {
if (stale) return
setTotalPages(Math.ceil(linkData.length / itemsPerPage))
setCurrentPage(1)
setDashboardData(
linkData.sort((a, b) => {
const dateA = new Date(a.date).getTime()
const dateB = new Date(b.date).getTime()
if (dateA === dateB) {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else {
return dateB - dateA
}
})
)
if (address) {
const links: string[] = []
const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
if (legacyLinkObject) {
legacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address: address })
if (raffleLegacyLinkObject) {
raffleLegacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
setLegacyLinks(links)
} else {
setLegacyLinks([])
}
setLegacyLinks(links)
} else {
setLegacyLinks([])
})
useEffect(() => {
let stale = false
composeLinkDataArray(address ?? '')
.then((linkData) => {
if (stale) return
setTotalPages(Math.ceil(linkData.length / itemsPerPage))
setCurrentPage(1)
setDashboardData(
linkData.sort((a, b) => {
const dateA = new Date(a.date).getTime()
const dateB = new Date(b.date).getTime()
if (dateA === dateB) {
return new Date(b.date).getTime() - new Date(a.date).getTime()
} else {
return dateB - dateA
}
})
)
if (address) {
const links: string[] = []
const legacyLinkObject = utils.getAllLinksFromLocalStorage({ address: address })
if (legacyLinkObject) {
legacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
const raffleLegacyLinkObject = utils.getAllRaffleLinksFromLocalstorage({ address: address })
if (raffleLegacyLinkObject) {
raffleLegacyLinkObject.forEach((obj) => {
links.push(obj.link)
})
}
setLegacyLinks(links)
} else {
setLegacyLinks([])
}
})
.catch((error) => {
if (stale) return
console.error('Failed to fetch link data:', error)
// Consider adding user feedback for the error state
})
}, [address, itemsPerPage]) // Make sure to include dependencies if needed

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/components/Dashboard/useDashboard.tsx (1)

140-156: 🛠️ Refactor suggestion

Add type information for history entries.

The TODO comment indicates missing type information. Using any type could lead to runtime errors.

interface HistoryEntry {
  uuid: string
  userRole: 'SENDER' | 'RECEIVER'
  amount: number
  tokenSymbol: string
  chainId: number
  timestamp: string
  status: string
  txHash?: string
}

Apply this diff to add type safety:

- requestHistory.entries.forEach((entry: any) => {
+ requestHistory.entries.forEach((entry: HistoryEntry) => {
🧹 Nitpick comments (3)
src/components/Dashboard/useDashboard.tsx (3)

1-13: Clean up unused imports.

Consider removing unused utility functions from the imports to maintain code cleanliness.

import {
    getTokenSymbol,
    getClaimedLinksFromLocalStorage,
    getCreatedLinksFromLocalStorage,
    getDirectSendFromLocalStorage,
    getOfframpClaimsFromLocalStorage,
-   getCashoutStatus,
} from '@/utils'

34-50: Improve error handling for offramp claims.

The current error handling defaults to 'claimed' status when an error occurs, which could be misleading. Consider:

  1. Using a more appropriate default status like 'error' or 'unknown'
  2. Adding more descriptive error messages for debugging
} catch (error) {
-    item.status = 'claimed'
+    item.status = 'error'
-    console.error(error)
+    console.error(`Error fetching offramp claim status for link ${item.link}:`, error)
}

163-218: Simplify date sorting logic.

The date sorting logic can be simplified by using a single comparison for both date and time.

case 'Date: new to old':
    _dashboardData.sort((a, b) => {
-       const dateA = new Date(a.date).getTime()
-       const dateB = new Date(b.date).getTime()
-       if (dateA === dateB) {
-           // If dates are equal, sort by time
-           return new Date(b.date).getTime() - new Date(a.date).getTime()
-       } else {
-           // Otherwise, sort by date
-           return dateB - dateA
-       }
+       return new Date(b.date).getTime() - new Date(a.date).getTime()
    })
    break
case 'Date: old to new':
    _dashboardData.sort((a, b) => {
-       const dateA = new Date(a.date).getTime()
-       const dateB = new Date(b.date).getTime()
-       if (dateA === dateB) {
-           // If dates are equal, sort by time
-           return new Date(a.date).getTime() - new Date(b.date).getTime()
-       } else {
-           // Otherwise, sort by date
-           return dateA - dateB
-       }
+       return new Date(a.date).getTime() - new Date(b.date).getTime()
    })
    break
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 250c197 and 30346e3.

📒 Files selected for processing (1)
  • src/components/Dashboard/useDashboard.tsx (10 hunks)

Comment on lines +62 to +68
const historyResponse = await fetch(`${PEANUT_API_URL}/users/history`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('jwt-token')}`,
},
})
const requestHistory = await historyResponse.json()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add error handling for the history API call.

The API call lacks error handling which could lead to runtime errors if the request fails.

-    const historyResponse = await fetch(`${PEANUT_API_URL}/users/history`, {
-        headers: {
-            'Content-Type': 'application/json',
-            Authorization: `Bearer ${Cookies.get('jwt-token')}`,
-        },
-    })
-    const requestHistory = await historyResponse.json()
+    let requestHistory = { entries: [] }
+    try {
+        const historyResponse = await fetch(`${PEANUT_API_URL}/users/history`, {
+            headers: {
+                'Content-Type': 'application/json',
+                Authorization: `Bearer ${Cookies.get('jwt-token')}`,
+            },
+        })
+        if (!historyResponse.ok) {
+            throw new Error(`HTTP error! status: ${historyResponse.status}`)
+        }
+        requestHistory = await historyResponse.json()
+    } catch (error) {
+        console.error('Failed to fetch request history:', error)
+    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const historyResponse = await fetch(`${PEANUT_API_URL}/users/history`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('jwt-token')}`,
},
})
const requestHistory = await historyResponse.json()
let requestHistory = { entries: [] }
try {
const historyResponse = await fetch(`${PEANUT_API_URL}/users/history`, {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('jwt-token')}`,
},
})
if (!historyResponse.ok) {
throw new Error(`HTTP error! status: ${historyResponse.status}`)
}
requestHistory = await historyResponse.json()
} catch (error) {
console.error('Failed to fetch request history:', error)
}

Copy link
Copy Markdown
Contributor

@kushagrasarathe kushagrasarathe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, approved for fast tracking, left a comment/thought

status: undefined,
message: link.reference ?? '',
attachmentUrl: link.attachmentUrl ?? '',
link: `${process.env.NEXT_PUBLIC_BASE_URL}/request/pay?id=${entry.uuid}`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: this /request/pay route might be conflicting with req v2 changes 👀

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a commit to #669

@jjramirezn jjramirezn merged commit 0077a34 into peanut-wallet-dev Feb 19, 2025
@jjramirezn jjramirezn deleted the feat/requests-in-history branch February 19, 2025 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants