Skip to content

Conversation

@envoy1084
Copy link
Contributor

@envoy1084 envoy1084 commented Jun 26, 2025

Fixes: #57, #66, #79, #80, #41

Improvements

  • Add Email Addresses in Account Dropdown with Copy Email Button.
  • Remove Card Header from Crypto to Fiat Page.
  • Remove Switch Wallet Button and use Disconnect Button in Payout page.
  • Disable Disconnect Button when payment is in progress.
  • Add Conditional Polling with hybrid server/client fetch mechanism to invoice data in payment page.
  • Block Creation of 0 value invoices, and propagate trpc error messages to frontend.
  • Fix Fit content width in dashboard (result attached below)
1.mp4

(result attached below)

Summary by CodeRabbit

  • New Features

    • User menu now displays the user's email in a truncated format, with an option to copy the full email address.
    • Added support for light theme mode.
  • Bug Fixes

    • Improved error handling and messaging when creating invoices, providing clearer feedback on failures.
    • Prevented creation of invoices with zero or negative total amounts.
  • Refactor

    • Updated payment section to use a polling mechanism for invoice status and improved wallet disconnect handling.
    • Simplified crypto-to-fiat compliance form layout by removing card styling.
  • Chores

    • Introduced a utility function for truncating email addresses.

@MantisClone
Copy link
Member

Hello @Envoy-VC, thank you for submitting your first pull request to the easy-invoice repository. We value your contribution and encourage you to review our contribution guidelines to ensure your submission meets our standards. Please note that every merged PR is automatically enrolled in our Best PR Initiative, offering a chance to win $500 each quarter. Our team is available via GitHub Discussions or Discord if you have any questions. Welcome aboard!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 26, 2025

Walkthrough

The changes introduce invoice polling and disconnect functionality to the payment section, add email display and copy capability to the user menu, improve error handling in invoice creation, and update UI components for consistency. A utility for truncating emails is added, and invoice creation is now validated for positive amounts.

Changes

File(s) Change Summary
src/app/invoices/[ID]/page.tsx Renamed the prop passed to PaymentSection from invoice to serverInvoice.
src/components/app-kit.tsx Added themeMode: "light" to createAppKit config.
src/components/crypto-to-fiat.tsx Removed Card-related wrappers; now uses a plain div for layout.
src/components/invoice-creator.tsx Added error handling to mutations; made onSubmit async and await invoice creation.
src/components/payment-section.tsx Renamed prop to serverInvoice; added polling for invoice status; added disconnect button and logic.
src/components/user-menu.tsx Extended props to include email; added truncated email display and copy-to-clipboard button.
src/lib/utils.ts Added truncateEmail utility function.
src/server/routers/invoice.ts Added validation for positive invoice amounts; improved error message propagation in mutations.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PaymentSection
    participant API
    participant AppKit

    User->>PaymentSection: Loads page with serverInvoice
    loop Every 3 seconds (while polling)
        PaymentSection->>API: Refetch invoice by ID
        API-->>PaymentSection: Returns updated invoice data
        PaymentSection->>PaymentSection: Update local invoice state
        alt Invoice status is "paid"
            PaymentSection->>PaymentSection: Stop polling
        end
    end
    User->>PaymentSection: Clicks "Disconnect"
    PaymentSection->>AppKit: Calls disconnect() if ready
Loading
sequenceDiagram
    participant User
    participant UserMenu
    participant Clipboard

    User->>UserMenu: Opens dropdown
    UserMenu->>UserMenu: Displays truncated email
    User->>UserMenu: Clicks copy button
    UserMenu->>Clipboard: Copies full email address
Loading

Possibly related PRs

  • #2: Modifies the same PaymentSection component and renames the invoice prop, directly related to the prop interface change.
  • #42: Also modifies PaymentSection with new payment routing and UI changes, related due to overlapping component modifications.

Suggested reviewers

  • MantisClone
  • bassgeta

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 68ef566 and 224c759.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • src/lib/utils.ts (1 hunks)
  • src/server/routers/invoice.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/utils.ts
  • src/server/routers/invoice.ts
✨ 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.

@MantisClone
Copy link
Member

Thank you for your submission! As you prepare for the review process, please ensure that your PR title, description, and any linked issues fully comply with our contribution guidelines. A clear explanation of your changes and their context will help expedite the review process. Every merged PR is automatically entered into our Best PR Initiative, offering a chance to win $500 every quarter. We appreciate your attention to detail and look forward to reviewing your contribution!

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: 0

🧹 Nitpick comments (2)
src/lib/utils.ts (1)

21-26: Add input validation for edge cases.

The function logic is sound, but consider adding validation for malformed emails and domain length constraints.

 export function truncateEmail(email: string, maxLength = 20): string {
+  if (!email || !email.includes('@')) return email;
   if (email.length <= maxLength) return email;
   const [user, domain] = email.split("@");
+  if (!user || !domain) return email;
   const keep = maxLength - domain.length - 4;
+  if (keep <= 0) return `...@${domain}`;
   return `${user.slice(0, keep)}...@${domain}`;
 }
src/components/user-menu.tsx (1)

52-68: Enhance clipboard operation with error handling and user feedback.

The email display and copy functionality implementation is good, but consider adding error handling and user feedback.

+import { toast } from "@/components/ui/use-toast"; // Assuming toast is available

             <Button
               variant="ghost"
               className="size-8"
               aria-label="Copy email"
               onClick={async () => {
-                await navigator.clipboard.writeText(user.email ?? "");
+                try {
+                  await navigator.clipboard.writeText(user.email ?? "");
+                  toast({
+                    title: "Email copied to clipboard",
+                    duration: 2000,
+                  });
+                } catch {
+                  // Fallback for older browsers or permission issues
+                  const textArea = document.createElement('textarea');
+                  textArea.value = user.email ?? "";
+                  document.body.appendChild(textArea);
+                  textArea.select();
+                  document.execCommand('copy');
+                  document.body.removeChild(textArea);
+                  toast({
+                    title: "Email copied to clipboard",
+                    duration: 2000,
+                  });
+                }
               }}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 52539a5 and 8393e3d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • package.json (1 hunks)
  • src/app/dashboard/page.tsx (1 hunks)
  • src/app/invoices/[ID]/page.tsx (1 hunks)
  • src/components/app-kit.tsx (1 hunks)
  • src/components/crypto-to-fiat.tsx (1 hunks)
  • src/components/invoice-creator.tsx (2 hunks)
  • src/components/payment-section.tsx (6 hunks)
  • src/components/user-menu.tsx (2 hunks)
  • src/lib/utils.ts (1 hunks)
  • src/server/routers/invoice.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: bassgeta
PR: RequestNetwork/easy-invoice#83
File: src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx:127-138
Timestamp: 2025-06-23T09:14:42.979Z
Learning: In the RequestNetwork/easy-invoice codebase, when suggesting improvements like error handling for transaction approvals, the user bassgeta prefers consistency over isolated improvements. They prefer not to implement error handling in one place unless it's done consistently across all similar transaction flows in the codebase.
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:316-319
Timestamp: 2025-05-19T13:00:48.790Z
Learning: The handleFormSubmit function in src/components/invoice-form.tsx correctly uses data.clientEmail from the form submission data to find matching payers, which is the proper implementation.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#21
File: src/app/invoices/[ID]/page.tsx:113-148
Timestamp: 2025-02-20T10:27:02.993Z
Learning: The easy-invoice project prefers simpler, direct implementations over abstract utilities. For example, using `.toFixed(2)` directly instead of creating separate number formatting utilities.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/app/invoices/[ID]/page.tsx:160-175
Timestamp: 2025-02-12T12:42:40.076Z
Learning: Invoice items are validated at creation time through the schema validation in src/lib/schemas/invoice.ts, ensuring that items array is non-empty and each item has required description, quantity, and price fields. Runtime validation in display components is not necessary.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#8
File: src/app/invoice-me/page.tsx:21-21
Timestamp: 2025-02-14T12:48:42.125Z
Learning: In the easy-invoice codebase, error handling for TRPC queries is not required at the component level as confirmed by the maintainer.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#64
File: src/components/batch-payout.tsx:100-106
Timestamp: 2025-06-04T10:08:40.123Z
Learning: In src/components/batch-payout.tsx, the user prefers to keep the simple 2-second timeout for AppKit initialization over more complex polling mechanisms when the current approach is working adequately. They favor simplicity over potentially more robust but complex solutions.
src/app/invoices/[ID]/page.tsx (5)
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:316-319
Timestamp: 2025-05-19T13:00:48.790Z
Learning: The handleFormSubmit function in src/components/invoice-form.tsx correctly uses data.clientEmail from the form submission data to find matching payers, which is the proper implementation.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:88-109
Timestamp: 2025-02-12T12:40:14.742Z
Learning: The payRequest endpoint in src/server/routers/invoice.ts is intentionally kept public (using publicProcedure) to allow invoice sharing and payment by anyone with the payment reference, similar to how payment links work in other payment systems.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#67
File: src/server/routers/payment.ts:47-49
Timestamp: 2025-06-04T12:02:39.411Z
Learning: In `src/server/routers/payment.ts`, the batchPay input validation already handles empty arrays correctly. The `batchPaymentFormSchema.shape.payouts.optional()` inherits the `.min(1, "At least one payment is required")` validation from the original schema, so empty payouts arrays are automatically rejected even when the field is made optional.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#42
File: src/components/payment-section.tsx:534-544
Timestamp: 2025-03-25T09:31:47.519Z
Learning: In the PaymentSection component of EasyInvoice, selectedRoute is automatically set to the first route when payment routes are loaded, and users can only switch between routes, not deselect them entirely.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/app/invoices/[ID]/page.tsx:160-175
Timestamp: 2025-02-12T12:42:40.076Z
Learning: Invoice items are validated at creation time through the schema validation in src/lib/schemas/invoice.ts, ensuring that items array is non-empty and each item has required description, quantity, and price fields. Runtime validation in display components is not necessary.
src/server/routers/invoice.ts (6)
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/app/invoices/[ID]/page.tsx:160-175
Timestamp: 2025-02-12T12:42:40.076Z
Learning: Invoice items are validated at creation time through the schema validation in src/lib/schemas/invoice.ts, ensuring that items array is non-empty and each item has required description, quantity, and price fields. Runtime validation in display components is not necessary.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:88-109
Timestamp: 2025-02-12T12:40:14.742Z
Learning: The payRequest endpoint in src/server/routers/invoice.ts is intentionally kept public (using publicProcedure) to allow invoice sharing and payment by anyone with the payment reference, similar to how payment links work in other payment systems.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#8
File: src/app/invoice-me/page.tsx:21-21
Timestamp: 2025-02-14T12:48:42.125Z
Learning: In the easy-invoice codebase, error handling for TRPC queries is not required at the component level as confirmed by the maintainer.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#67
File: src/server/routers/payment.ts:47-49
Timestamp: 2025-06-04T12:02:39.411Z
Learning: In `src/server/routers/payment.ts`, the batchPay input validation already handles empty arrays correctly. The `batchPaymentFormSchema.shape.payouts.optional()` inherits the `.min(1, "At least one payment is required")` validation from the original schema, so empty payouts arrays are automatically rejected even when the field is made optional.
Learnt from: MantisClone
PR: RequestNetwork/easy-invoice#59
File: src/app/api/webhook/route.ts:77-95
Timestamp: 2025-05-22T18:19:12.366Z
Learning: For webhook handlers in the Easy Invoice project, unknown or unexpected subStatus values in payment processing should be treated as errors (using console.error) rather than warnings, and should return a 422 Unprocessable Entity status code.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#23
File: src/components/direct-payment.tsx:343-360
Timestamp: 2025-02-27T14:02:35.047Z
Learning: For the DirectPayment component, amount validation is already handled through Zod schema validation in paymentFormSchema, which ensures the amount is greater than zero.
src/components/invoice-creator.tsx (8)
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:316-319
Timestamp: 2025-05-19T13:00:48.790Z
Learning: The handleFormSubmit function in src/components/invoice-form.tsx correctly uses data.clientEmail from the form submission data to find matching payers, which is the proper implementation.
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:451-453
Timestamp: 2025-05-20T12:59:44.665Z
Learning: In the Easy Invoice project, setTimeout is required when submitting a form after modal state changes in the crypto-to-fiat payment flow. Directly calling handleFormSubmit without setTimeout after closing modals and updating state causes issues.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/app/invoices/[ID]/page.tsx:160-175
Timestamp: 2025-02-12T12:42:40.076Z
Learning: Invoice items are validated at creation time through the schema validation in src/lib/schemas/invoice.ts, ensuring that items array is non-empty and each item has required description, quantity, and price fields. Runtime validation in display components is not necessary.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#8
File: src/app/invoice-me/page.tsx:21-21
Timestamp: 2025-02-14T12:48:42.125Z
Learning: In the easy-invoice codebase, error handling for TRPC queries is not required at the component level as confirmed by the maintainer.
Learnt from: MantisClone
PR: RequestNetwork/easy-invoice#59
File: src/app/api/webhook/route.ts:77-95
Timestamp: 2025-05-22T18:19:12.366Z
Learning: For webhook handlers in the Easy Invoice project, unknown or unexpected subStatus values in payment processing should be treated as errors (using console.error) rather than warnings, and should return a 422 Unprocessable Entity status code.
Learnt from: bassgeta
PR: RequestNetwork/easy-invoice#83
File: src/components/create-recurring-payment/blocks/create-recurring-payment-form.tsx:127-138
Timestamp: 2025-06-23T09:14:42.979Z
Learning: In the RequestNetwork/easy-invoice codebase, when suggesting improvements like error handling for transaction approvals, the user bassgeta prefers consistency over isolated improvements. They prefer not to implement error handling in one place unless it's done consistently across all similar transaction flows in the codebase.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#8
File: src/server/routers/invoice-me.ts:25-29
Timestamp: 2025-02-14T12:48:33.762Z
Learning: In the easy-invoice project, database operation error handling is handled at a different level, and explicit try-catch blocks around individual database operations are not required.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:88-109
Timestamp: 2025-02-12T12:40:14.742Z
Learning: The payRequest endpoint in src/server/routers/invoice.ts is intentionally kept public (using publicProcedure) to allow invoice sharing and payment by anyone with the payment reference, similar to how payment links work in other payment systems.
src/components/payment-section.tsx (8)
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:316-319
Timestamp: 2025-05-19T13:00:48.790Z
Learning: The handleFormSubmit function in src/components/invoice-form.tsx correctly uses data.clientEmail from the form submission data to find matching payers, which is the proper implementation.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:88-109
Timestamp: 2025-02-12T12:40:14.742Z
Learning: The payRequest endpoint in src/server/routers/invoice.ts is intentionally kept public (using publicProcedure) to allow invoice sharing and payment by anyone with the payment reference, similar to how payment links work in other payment systems.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#64
File: src/components/batch-payout.tsx:100-106
Timestamp: 2025-06-04T10:08:40.123Z
Learning: In src/components/batch-payout.tsx, the user prefers to keep the simple 2-second timeout for AppKit initialization over more complex polling mechanisms when the current approach is working adequately. They favor simplicity over potentially more robust but complex solutions.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#2
File: src/server/routers/invoice.ts:0-0
Timestamp: 2025-02-12T13:04:46.135Z
Learning: The `payRequest` function in the invoice router retrieves payment transactions calldata from the Request API and does not process the payment itself. The actual payment status update happens through the webhook handler.
Learnt from: rodrigopavezi
PR: RequestNetwork/easy-invoice#45
File: src/components/invoice-form.tsx:451-453
Timestamp: 2025-05-20T12:59:44.665Z
Learning: In the Easy Invoice project, setTimeout is required when submitting a form after modal state changes in the crypto-to-fiat payment flow. Directly calling handleFormSubmit without setTimeout after closing modals and updating state causes issues.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#67
File: src/server/routers/payment.ts:47-49
Timestamp: 2025-06-04T12:02:39.411Z
Learning: In `src/server/routers/payment.ts`, the batchPay input validation already handles empty arrays correctly. The `batchPaymentFormSchema.shape.payouts.optional()` inherits the `.min(1, "At least one payment is required")` validation from the original schema, so empty payouts arrays are automatically rejected even when the field is made optional.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#42
File: src/components/payment-section.tsx:534-544
Timestamp: 2025-03-25T09:31:47.519Z
Learning: In the PaymentSection component of EasyInvoice, selectedRoute is automatically set to the first route when payment routes are loaded, and users can only switch between routes, not deselect them entirely.
Learnt from: aimensahnoun
PR: RequestNetwork/easy-invoice#23
File: src/components/direct-payment.tsx:63-89
Timestamp: 2025-02-27T13:58:33.590Z
Learning: The AppKit wallet module requires initialization time before it's ready for use. A 2-second delay is intentionally used in the DirectPayment component to ensure the wallet is fully initialized before allowing interactions.
🧬 Code Graph Analysis (2)
src/components/user-menu.tsx (4)
src/server/db/schema.ts (1)
  • User (274-274)
src/components/ui/dropdown-menu.tsx (1)
  • DropdownMenuLabel (191-191)
src/lib/utils.ts (1)
  • truncateEmail (21-26)
src/components/ui/button.tsx (1)
  • Button (56-56)
src/components/payment-section.tsx (1)
src/server/db/schema.ts (1)
  • Request (273-273)
🔇 Additional comments (18)
src/app/dashboard/page.tsx (1)

31-31: LGTM! Layout improvement aligns with PR objectives.

The reduction from max-w-7xl to max-w-5xl with added w-full properly constrains the dashboard content width while ensuring full utilization of available space.

src/components/crypto-to-fiat.tsx (1)

1-1: LGTM! Correct cleanup of unused import.

Removing the unused CardHeader import aligns with the PR objective to remove the card header from the Crypto to Fiat page.

src/components/user-menu.tsx (1)

12-12: LGTM! Proper imports and interface updates.

The imports and props interface changes correctly support the new email display functionality.

Also applies to: 15-15, 19-19

package.json (1)

34-35: Verify the updated dependency versions are secure and compatible.

The AppKit dependencies were updated from ^1.6.8 to ^1.7.11. Ensure these versions exist and are free from known vulnerabilities.

#!/bin/bash
# Description: Verify AppKit dependency versions and check for security advisories

echo "Checking @reown/appkit version availability..."
npm view @reown/appkit@1.7.11 version 2>/dev/null || echo "Version 1.7.11 not found"

echo "Checking @reown/appkit-adapter-ethers5 version availability..."
npm view @reown/appkit-adapter-ethers5@1.7.11 version 2>/dev/null || echo "Version 1.7.11 not found"

echo "Checking for recent versions..."
npm view @reown/appkit versions --json | jq '.[-5:]' 2>/dev/null || echo "Unable to fetch version history"

echo "Checking npm audit for known vulnerabilities..."
npm audit --audit-level moderate --json 2>/dev/null | jq '.vulnerabilities' || echo "Unable to run audit check"
src/server/routers/invoice.ts (3)

25-31: LGTM! Excellent validation to prevent zero-value invoices.

The validation correctly prevents creation of invoices with non-positive total amounts and provides a clear error message. This addresses the PR objective effectively.


161-163: LGTM! Improved error handling with meaningful messages.

The enhanced error handling properly propagates the original error message when available, providing better debugging information while maintaining a fallback for unexpected error types.


215-217: LGTM! Consistent error handling implementation.

The error handling for createFromInvoiceMe is consistent with the create endpoint, ensuring uniform error reporting across both invoice creation flows.

src/components/app-kit.tsx (1)

31-31: LGTM! Theme configuration improves UI consistency.

The addition of themeMode: "light" ensures a consistent light theme experience, which aligns with the dependency update to AppKit v1.7.11.

src/app/invoices/[ID]/page.tsx (1)

51-51: LGTM! Prop name clarifies data source for enhanced PaymentSection.

The prop name change from invoice to serverInvoice better reflects that PaymentSection now manages local state and polling, making the data flow clearer.

src/components/invoice-creator.tsx (3)

47-54: LGTM! Excellent error handling with user-friendly feedback.

The onError callback provides immediate toast feedback with detailed error messages when available, improving the user experience during invoice creation failures.


62-69: LGTM! Consistent error handling across mutation variants.

The error handling for the regular create mutation mirrors the createFromInvoiceMe implementation, ensuring consistent user feedback across both invoice creation flows.


91-93: LGTM! Proper async handling of mutation calls.

Converting onSubmit to async and awaiting the createInvoice call ensures proper error handling flow and allows the try-catch block to capture any exceptions from the mutation.

src/components/payment-section.tsx (6)

20-20: LGTM!

The import of useDisconnect hook is correctly added and will be used for wallet disconnection functionality.


44-44: LGTM!

The prop rename from invoice to serverInvoice improves clarity by distinguishing between server-side data and local state.


105-107: LGTM!

The function signature update and useDisconnect hook usage are correctly implemented.


215-220: LGTM!

The disconnect handler is properly implemented with appropriate safety checks for app kit readiness.


539-543: Excellent UI improvement!

The change from "Switch Wallet" to "Disconnect" is more intuitive and user-friendly. The disable condition properly prevents disconnection during payment processing, which enhances UX by preventing payment interruptions.


116-127: Verify polling trigger and consider React Query best practices.

The polling implementation has a couple of concerns:

  1. The polling state is initialized as false but I don't see where it's set to true in this component. The polling mechanism won't activate without a trigger.

  2. The onSuccess callback is deprecated in newer versions of React Query/TanStack Query. Consider using useEffect with the data instead.

Let me check where the polling is triggered:

#!/bin/bash
# Search for where polling state is set to true
rg -A 3 -B 3 "setPolling\(true\)"

Consider this refactor for the polling logic:

- // Poll the invoice status every 3 seconds until it's paid
- api.invoice.getById.useQuery(serverInvoice.id, {
-   enabled: polling,
-   refetchInterval: polling ? 3000 : false,
-   onSuccess: (data) => {
-     setInvoice(data);
-     if (data.status === "paid") setPolling(false);
-   },
- });
+ // Poll the invoice status every 3 seconds until it's paid
+ const { data: polledInvoice } = api.invoice.getById.useQuery(serverInvoice.id, {
+   enabled: polling,
+   refetchInterval: polling ? 3000 : false,
+ });
+ 
+ useEffect(() => {
+   if (polledInvoice) {
+     setInvoice(polledInvoice);
+     if (polledInvoice.status === "paid") setPolling(false);
+   }
+ }, [polledInvoice]);

Copy link
Contributor

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

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

Thanks for this PR, really straight to the point and it fixes a lot of cosmetic issues and wonky behaviour!

  1. The email address is added to the dropdown ✔️
image 2. The crypto to fiat card header is removed, but the card is now nested inside another card, could we make it just one card? SImilar to how we have it elsewhere in our app. image image 3. Payouts now has light mode AppKit and the menu allows the user to disconnect ✔️ image 4. The disconnect button is disabled when a payment is being approved ✔️ image 5. The polling doesn't work properly for me, the status doesn't change
invoice-polling-2025-07-16_10.42.06.mp4
  1. 0 value invoices aren't created ✔️
image
  1. The dashboard now fits most screen widths nicely 😎
dashboard-width-2025-07-16_10.58.12.mp4

overall a great start, if you fix that card and iron out the polling issue I'll be super stoked to approve your worthy contribution to Easy Invoice 🫡

@envoy1084
Copy link
Contributor Author

Hey @bassgeta

I have removed the nested card header and fixed polling logic

Easy Invoice

polling.mp4

@envoy1084 envoy1084 requested a review from bassgeta July 17, 2025 03:22
Copy link
Contributor

@bassgeta bassgeta left a comment

Choose a reason for hiding this comment

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

Smashed it right out the park 💪

  1. No more nested header ✔️
image 2. The polling now works as it should ✔️ image

@aimensahnoun
Copy link
Member

Awesome work @Envoy-VC. feel free to merge the PR

@MantisClone MantisClone merged commit 3822b0e into RequestNetwork:main Jul 21, 2025
5 checks passed
@github-project-automation github-project-automation bot moved this from 👀 In Review to ✅ Done in Request Network Tech Backlog Jul 21, 2025
@MantisClone
Copy link
Member

Congratulations, your pull request has been merged! Thank you for your valuable contribution to Request Network. As a reminder, every merged PR is automatically entered into our Best PR Initiative, offering a quarterly prize of $500. Your work significantly supports our project's growth, and we encourage you to continue engaging with our community. Additionally, if you want to build or add crypto payments and invoicing features, explore how our API can reduce deployment time from months to hours while offering advanced features. Book a call with our expert to learn more and fast-track your development.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment