-
Notifications
You must be signed in to change notification settings - Fork 7
feat: UI Improvements and Quality Fixes #86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: UI Improvements and Quality Fixes #86
Conversation
…nd propogate error messages from trpc to client
|
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! |
WalkthroughThe 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
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
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
Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
|
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! |
There was a problem hiding this 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis 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-7xltomax-w-5xlwith addedw-fullproperly 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
CardHeaderimport 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.8to^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
createFromInvoiceMeis consistent with thecreateendpoint, 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
invoicetoserverInvoicebetter 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
onErrorcallback 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
createmutation mirrors thecreateFromInvoiceMeimplementation, ensuring consistent user feedback across both invoice creation flows.
91-93: LGTM! Proper async handling of mutation calls.Converting
onSubmitto async and awaiting thecreateInvoicecall 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
useDisconnecthook is correctly added and will be used for wallet disconnection functionality.
44-44: LGTM!The prop rename from
invoicetoserverInvoiceimproves clarity by distinguishing between server-side data and local state.
105-107: LGTM!The function signature update and
useDisconnecthook 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:
The
pollingstate is initialized asfalsebut I don't see where it's set totruein this component. The polling mechanism won't activate without a trigger.The
onSuccesscallback is deprecated in newer versions of React Query/TanStack Query. Consider usinguseEffectwith 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]);
bassgeta
left a comment
There was a problem hiding this 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!
- The email address is added to the dropdown ✔️
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.
3. Payouts now has light mode AppKit and the menu allows the user to disconnect ✔️
4. The disconnect button is disabled when a payment is being approved ✔️
5. The polling doesn't work properly for me, the status doesn't change
invoice-polling-2025-07-16_10.42.06.mp4
- 0 value invoices aren't created ✔️
- 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 🫡
|
Hey @bassgeta I have removed the nested card header and fixed polling logic polling.mp4 |
bassgeta
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Awesome work @Envoy-VC. feel free to merge the PR |
|
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. |



Fixes: #57, #66, #79, #80, #41
Improvements
1.mp4
(result attached below)
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores