Skip to content

Conversation

kushagrasarathe
Copy link
Contributor

  • contributes to TASK-11685 : standalone receipt page without a drawer for direct send and claimed send links

Copy link

vercel bot commented Jun 2, 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 Jun 2, 2025 4:41pm

Copy link
Contributor

coderabbitai bot commented Jun 2, 2025

## Walkthrough

This update refactors transaction detail display logic by separating the drawer container and receipt content into distinct components. It updates transaction link generation for direct sends, modifies metadata titles, and replaces usage of the old drawer component with the new receipt component in relevant modules. Internal state and rendering logic are reorganized accordingly.

## Changes

| Files/Groups                                                         | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
|---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| src/app/(mobile-ui)/history/layout.tsx                              | Changed page metadata title from "Transaction History | Peanut" to "History | Peanut".                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| src/app/[...recipient]/client.tsx, src/components/Claim/Claim.tsx   | Replaced `TransactionDetailsDrawer` with `TransactionDetailsReceipt`. Updated logic for resolving usernames, user roles, and drawer state. Adjusted rendering to use the new receipt component and removed old drawer usage. Imports reorganized in Claim.tsx.                                                                                                                                                                                                                                                                                                                                                           |
| src/components/TransactionDetails/TransactionDetailsDrawer.tsx      | Refactored to separate the drawer and receipt into `TransactionDetailsDrawer` and new `TransactionDetailsReceipt` components. Introduced dynamic height calculation for the drawer, reorganized async actions and conditional rendering, and modularized transaction actions (share, cancel, pay, reject). Added export for `TransactionDetailsReceipt`.                                                                                                                                                |
| src/hooks/useTransactionHistory.ts                                  | Added construction of a `link` URL for `'DIRECT_SEND'` transaction entries, forming a shareable link with recipient and charge ID. No other logic changed.                                                                                                                                                                                                                                                                                                                                                                                     |

## Possibly related PRs

- peanutprotocol/peanut-ui#858: Refactors `TransactionDetailsDrawer` to delegate receipt rendering to `TransactionDetailsReceipt` and adds attachment download link rendering inside the receipt, closely related to the modularization and UI changes in this PR.

## Suggested reviewers

- jjramirezn
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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.

Copy link

Copy link
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: 3

🧹 Nitpick comments (1)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (1)

80-446: Consider breaking down this large component for better maintainability.

The TransactionDetailsReceipt component handles many responsibilities. Consider:

  • Extracting action handlers (cancel, pay, reject) into separate functions or custom hooks
  • Creating sub-components for different transaction states (pending requests, sent links, etc.)
  • Moving complex conditional logic to helper functions

This would improve readability and testability.

🧰 Tools
🪛 Biome (1.9.4)

[error] 226-236: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ea765b0 and 67cccdd.

📒 Files selected for processing (5)
  • src/app/(mobile-ui)/history/layout.tsx (1 hunks)
  • src/app/[...recipient]/client.tsx (4 hunks)
  • src/components/Claim/Claim.tsx (2 hunks)
  • src/components/TransactionDetails/TransactionDetailsDrawer.tsx (5 hunks)
  • src/hooks/useTransactionHistory.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/hooks/useTransactionHistory.ts (1)
src/constants/general.consts.ts (1)
  • BASE_URL (43-43)
🪛 Biome (1.9.4)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx

[error] 226-236: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (10)
src/app/(mobile-ui)/history/layout.tsx (1)

6-6: LGTM! Clean title simplification.

The shortened title "History | Peanut" is more concise while maintaining clarity. This change aligns well with the overall UI improvements in this PR.

src/hooks/useTransactionHistory.ts (1)

170-170: Excellent consistency with existing link generation pattern.

The link generation for DIRECT_SEND transactions follows the exact same pattern as REQUEST transactions (line 165), using proper fallback logic and consistent URL structure. This supports the PR's goal of enabling shareable direct send links.

src/components/Claim/Claim.tsx (2)

3-22: Clean import reorganization.

The import consolidation removes duplicates and groups related imports together, improving code organization.


278-278: Proper component replacement aligns with architectural refactor.

The replacement of TransactionDetailsDrawer with TransactionDetailsReceipt correctly implements the separation of drawer container from receipt content. The new component receives the transaction data directly without needing drawer-specific props.

src/app/[...recipient]/client.tsx (4)

11-11: Import updated to match architectural refactor.

Correctly imports TransactionDetailsReceipt instead of TransactionDetailsDrawer, aligning with the separation of drawer container and receipt content.


258-262: Robust username resolution with proper fallbacks.

The enhanced fallback chain ensures username resolution works correctly:

  1. First tries recipientAccount.user.username
  2. Falls back to recipientAccount.identifier
  3. Finally uses chargeDetails.requestLink.recipientAddress

The originalUserRole logic correctly determines user role based on whether current user is the recipient.


274-276: Improved specificity for link transaction detection.

The updated isLinkTransaction logic is more precise - it only sets to true when the original user role is sender AND the current user matches. This prevents incorrect link transaction flags and provides better context for the receipt component.


402-403: Clean conditional rendering with new receipt component.

The replacement of TransactionDetailsDrawer with TransactionDetailsReceipt in the conditional rendering maintains the same logic flow while using the new modular component architecture. The transaction data is passed directly as a prop.

src/components/TransactionDetails/TransactionDetailsDrawer.tsx (2)

35-78: Well-structured drawer container component.

The separation of drawer container logic from receipt content is a good architectural decision. The dynamic height calculation with constraints provides a better user experience.


80-90: Excellent refactoring to support standalone receipts.

The separation of TransactionDetailsReceipt from the drawer container successfully achieves the PR objective of enabling standalone receipt display. The component can now be used independently while maintaining backward compatibility through the optional props.

Comment on lines +309 to +323
sendLinksApi
.claim(user!.user.username!, transaction.extraDataForDrawer!.link!)
.then(() => {
// Claiming takes time, so we need to invalidate both transaction query types
setTimeout(() => {
fetchBalance()
queryClient
.invalidateQueries({
queryKey: [TRANSACTIONS],
})
.then(() => {
setIsLoading(false)
onClose()
})
}, 3000)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace setTimeout with proper async handling.

Using a fixed 3-second delay is unreliable for waiting on async operations. Consider implementing proper promise chaining or polling to check when the claim operation is actually complete.

-                                    sendLinksApi
-                                        .claim(user!.user.username!, transaction.extraDataForDrawer!.link!)
-                                        .then(() => {
-                                            // Claiming takes time, so we need to invalidate both transaction query types
-                                            setTimeout(() => {
-                                                fetchBalance()
-                                                queryClient
-                                                    .invalidateQueries({
-                                                        queryKey: [TRANSACTIONS],
-                                                    })
-                                                    .then(() => {
-                                                        setIsLoading(false)
-                                                        onClose()
-                                                    })
-                                            }, 3000)
-                                        })
+                                    sendLinksApi
+                                        .claim(user!.user.username!, transaction.extraDataForDrawer!.link!)
+                                        .then(async () => {
+                                            // Wait for claim to be processed
+                                            await fetchBalance()
+                                            await queryClient.invalidateQueries({
+                                                queryKey: [TRANSACTIONS],
+                                            })
+                                            setIsLoading(false)
+                                            onClose()
+                                        })
📝 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
sendLinksApi
.claim(user!.user.username!, transaction.extraDataForDrawer!.link!)
.then(() => {
// Claiming takes time, so we need to invalidate both transaction query types
setTimeout(() => {
fetchBalance()
queryClient
.invalidateQueries({
queryKey: [TRANSACTIONS],
})
.then(() => {
setIsLoading(false)
onClose()
})
}, 3000)
sendLinksApi
.claim(user!.user.username!, transaction.extraDataForDrawer!.link!)
.then(async () => {
// Wait for claim to be processed
await fetchBalance()
await queryClient.invalidateQueries({
queryKey: [TRANSACTIONS],
})
setIsLoading(false)
onClose()
})
🤖 Prompt for AI Agents
In src/components/TransactionDetails/TransactionDetailsDrawer.tsx around lines
309 to 323, the code uses a fixed 3-second setTimeout to wait after the claim
API call, which is unreliable. Replace the setTimeout with proper async handling
by chaining promises or awaiting the completion of the claim operation and
subsequent fetchBalance and queryClient.invalidateQueries calls. Ensure that
setIsLoading(false) and onClose() are only called after all async operations
have fully completed.

Copy link
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 (2)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (2)

225-235: Remove unnecessary Fragment wrapper.

This is a duplicate of a previous review comment. The Fragment is redundant as it contains only one conditional block.

-                            <>
-                                {transaction.cancelledDate && (
-                                    <PaymentInfoRow
-                                        label="Cancelled"
-                                        value={formatDate(transaction.cancelledDate as Date)}
-                                        hideBottomBorder={
-                                            !transaction.fee && !transaction.memo && !transaction.attachmentUrl
-                                        }
-                                    />
-                                )}
-                            </>
+                            {transaction.cancelledDate && (
+                                <PaymentInfoRow
+                                    label="Cancelled"
+                                    value={formatDate(transaction.cancelledDate as Date)}
+                                    hideBottomBorder={
+                                        !transaction.fee && !transaction.memo && !transaction.attachmentUrl
+                                    }
+                                />
+                            )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 225-235: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


308-328: Replace setTimeout with proper async handling.

This is a duplicate of a previous review comment. Using a fixed 3-second delay is unreliable for waiting on async operations. The claim operation should use proper promise chaining.

-                                        .then(() => {
-                                            // Claiming takes time, so we need to invalidate both transaction query types
-                                            setTimeout(() => {
-                                                fetchBalance()
-                                                queryClient
-                                                    .invalidateQueries({
-                                                        queryKey: [TRANSACTIONS],
-                                                    })
-                                                    .then(() => {
-                                                        setIsLoading(false)
-                                                        onClose()
-                                                    })
-                                            }, 3000)
-                                        })
+                                        .then(async () => {
+                                            // Wait for claim to be processed
+                                            await fetchBalance()
+                                            await queryClient.invalidateQueries({
+                                                queryKey: [TRANSACTIONS],
+                                            })
+                                            setIsLoading(false)
+                                            onClose()
+                                        })
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 67cccdd and 3707527.

📒 Files selected for processing (1)
  • src/components/TransactionDetails/TransactionDetailsDrawer.tsx (5 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx

[error] 225-235: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Deploy-Preview
🔇 Additional comments (5)
src/components/TransactionDetails/TransactionDetailsDrawer.tsx (5)

38-55: LGTM: Clean refactor with proper state management.

The introduction of internal loading state management and the memoized close handler improves the component's encapsulation and performance. The dynamic height calculation using the custom hook is a good approach for responsive UI.


70-76: Good separation of concerns.

Delegating the content rendering to TransactionDetailsReceipt while keeping the drawer container logic separate is excellent architectural design. This makes the components more reusable and testable.


386-429: LGTM: Comprehensive requestee action handling.

The conditional rendering for pay and reject buttons when the user is a pending requestee is well-implemented. The pay action correctly redirects to the transaction link, and the reject action follows the proper async pattern.


303-304: Good defensive programming with required props.

The conditional checks for setIsLoading && onClose before rendering action buttons ensure the component gracefully handles cases where these props are not provided. This makes the component more robust when used in different contexts.

Also applies to: 353-353, 386-386


123-128:

❓ Verification inconclusive

Verify the share receipt logic.

The shouldShowShareReceipt logic excludes pending transactions and specific directions, but includes transactions with txHash and non-receive/non-request_sent directions. Please verify this logic aligns with the business requirements for when users should be able to share receipts.


🏁 Script executed:

#!/bin/bash
# Description: Search for other usages of share receipt functionality to understand the expected behavior
# Expected: Find patterns or documentation about when receipts should be shareable

# Search for share receipt related code
rg -A 3 -B 3 "share.*receipt|receipt.*share" --type tsx --type ts

# Search for transaction direction patterns
rg -A 2 -B 2 "direction.*receive|direction.*request_sent" --type tsx --type ts

Length of output: 204


🏁 Script executed:

#!/bin/bash
# Revised search using file globs for .tsx and .ts to avoid unrecognized file type errors

# 1. Search for share receipt related code snippets across the codebase
rg -g '*.tsx' -g '*.ts' -A3 -B3 "share.*receipt|receipt.*share"

# 2. Search for transaction direction checks to see how 'receive' and 'request_sent' are used elsewhere
rg -g '*.tsx' -g '*.ts' -A2 -B2 "direction.*receive|direction.*request_sent"

# 3. Locate where shouldShowShareReceipt is referenced in TransactionDetailsDrawer
rg "shouldShowShareReceipt" -n src/components/TransactionDetails/TransactionDetailsDrawer.tsx

Length of output: 3719


Please confirm share-receipt eligibility against business requirements
I reviewed the code and found that shouldShowShareReceipt only returns true when:

  • transaction.txHash is present
  • transaction.direction is neither 'receive' nor 'request_sent'
  • no pending states (isPendingSentLink, isPendingRequester, isPendingRequestee)

No other references to “receipt” or “share receipt” were found in the codebase.
• File: src/components/TransactionDetails/TransactionDetailsDrawer.tsx (lines 123–128)
• UI hook: {shouldShowShareReceipt && transaction.extraDataForDrawer?.link && ( … )}

Since there’s no in-code documentation or usage examples, please verify this matches the product spec for when users should be able to share receipts.

Comment on lines +354 to +383
<Button
icon="cancel"
iconContainerClassName="border border-black w-4 h-4 mr-1 rounded-full"
iconClassName="p-1"
onClick={() => {
setIsLoading(true)
chargesApi
.cancel(transaction.id)
.then(() => {
queryClient
.invalidateQueries({
queryKey: [TRANSACTIONS],
})
.then(() => {
setIsLoading(false)
onClose()
})
})
.catch((error) => {
captureException(error)
console.error('Error canceling charge:', error)
setIsLoading(false)
})
}}
variant={'primary-soft'}
shadowSize="4"
className="flex w-full items-center gap-1"
>
Cancel request
</Button>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Inconsistent async handling pattern.

The cancel request button properly chains promises without setTimeout, but the cancel link button (lines 308-328) uses setTimeout. Consider unifying the async handling approach for consistency.

The current implementation correctly handles promise chaining:

.then(() => {
    queryClient
        .invalidateQueries({
            queryKey: [TRANSACTIONS],
        })
        .then(() => {
            setIsLoading(false)
            onClose()
        })
})

This pattern should be applied to the cancel link functionality as well.

🤖 Prompt for AI Agents
In src/components/TransactionDetails/TransactionDetailsDrawer.tsx around lines
308 to 328, the cancel link button uses setTimeout for async handling, which is
inconsistent with the cancel request button's proper promise chaining seen in
lines 354 to 383. Refactor the cancel link button's async code to remove
setTimeout and instead chain promises directly, following the pattern used in
the cancel request button: call chargesApi.cancel, then invalidate queries with
queryClient.invalidateQueries, and finally update loading state and close the
drawer in the then callbacks.

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