Skip to content

feat: added downloadable invoice button#116

Open
omsherikar wants to merge 1 commit intomainfrom
feat/dodo-billing-history
Open

feat: added downloadable invoice button#116
omsherikar wants to merge 1 commit intomainfrom
feat/dodo-billing-history

Conversation

@omsherikar
Copy link
Copy Markdown
Collaborator

@omsherikar omsherikar commented Mar 25, 2026

Summary by CodeRabbit

  • New Features

    • Added Invoice column to the billing history table, providing downloadable invoice links for payments with available invoices and displaying an unavailable status for payments without invoices.
  • Style

    • Updated billing table cell styling: Date columns now display with medium font weight, and Amount columns no longer use white text color.

Copilot AI review requested due to automatic review settings March 25, 2026 07:39
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
refactron Ready Ready Preview, Comment Mar 25, 2026 7:39am

@github-actions github-actions bot added type:refactor Code refactoring type:feature New feature labels Mar 25, 2026
@github-actions
Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA e6bbd82.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Scanned Files

None

@github-actions
Copy link
Copy Markdown

👋 Thanks for opening this pull request! A maintainer will review it soon. Please make sure all CI checks pass.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an “Invoice” column to the Billing History table so users can open/download an invoice when an invoiceUrl is available.

Changes:

  • Adds an “Invoice” table column with a conditional “Download” link (or “Unavailable” state).
  • Updates some table cell styling for the billing history rows.
  • Modifies plan card border class logic in the upgrade plan selection UI.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 378 to +380
plan.highlight &&
selectedPlan !== plan.id &&
'border-amber-500/30'
selectedPlan !== plan.id &&
'border-amber-500/30'
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

The amber border highlight is now applied to every non-selected plan because the plan.highlight && guard was removed. This makes all unselected plans look "highlighted" and decouples the border styling from the Most Popular badge logic below. Restore the plan.highlight condition (or otherwise tie the border class to the same highlight rule).

Copilot uses AI. Check for mistakes.
Comment on lines +332 to +335
{payment.invoiceUrl ? (
<a
href={payment.invoiceUrl}
target="_blank"
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

payment.invoiceUrl is rendered directly into an href. If this value can ever be influenced by API data, a javascript:/non-http(s) URL could become a clickable XSS vector. Consider validating/normalizing the URL before rendering (e.g., only allow http/https and otherwise treat it as unavailable).

Copilot uses AI. Check for mistakes.
Comment on lines +331 to +333
<td className="py-4 text-right">
{payment.invoiceUrl ? (
<a
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

With the new invoiceUrl field, the billingHistory items are implicitly expected to have a specific shape, but the state is typed as any[]. This makes it easy to ship runtime errors (e.g., missing currency, status, invoiceUrl). Define a BillingHistoryItem type/interface (with invoiceUrl?: string) and use it for billingHistory and the map callback.

Copilot uses AI. Check for mistakes.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

Added a new "Invoice" column to the billing history table that displays a download link when payment.invoiceUrl is available, or "Unavailable" with a tooltip when not. Updated styling for "Date" and "Amount" columns.

Changes

Cohort / File(s) Summary
Billing Invoice Column
src/components/Billing.tsx
Added "Invoice" column to billing table with conditional rendering: displays external download link when invoice URL exists, otherwise shows muted "Unavailable" text with tooltip. Updated "Date" cell styling to use font-medium and removed text-white from "Amount" cell.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~4 minutes

Poem

🐰 A column springs forth with invoices so fine,
Download them quick—no waiting in line!
When URLs hide, we show you "Not here,"
With tooltips and grace, the message is clear! 📄✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a downloadable invoice feature to the billing history table. It is concise, specific, and clearly relates to the primary modification in the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dodo-billing-history

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Billing.tsx`:
- Around line 342-343: Prettier formatting is failing in the Billing component
around the JSX that renders the "Unavailable" span; run Prettier on
src/components/Billing.tsx to reformat the JSX (the span with className
"text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" and
the surrounding JSX blocks around lines where "Unavailable" appears, and the
similar JSX near lines 379-380) so the file conforms to project Prettier rules
and the CI pipeline will pass.
- Around line 332-345: Validate payment.invoiceUrl before rendering the anchor:
implement or call a helper (e.g., isValidInvoiceUrl) that attempts to construct
a URL object from payment.invoiceUrl and ensures url.protocol === 'https:'
(reject malformed or non-HTTPS URLs), then render the <a> only when that
validation passes and fall back to the "Unavailable" <span> otherwise; update
the conditional around payment.invoiceUrl in the Billing component to use that
validation check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 287a8ec1-92ae-485a-bff4-8154008ae397

📥 Commits

Reviewing files that changed from the base of the PR and between 4c512a7 and e6bbd82.

📒 Files selected for processing (1)
  • src/components/Billing.tsx

Comment on lines +332 to +345
{payment.invoiceUrl ? (
<a
href={payment.invoiceUrl}
target="_blank"
rel="noopener noreferrer"
className="text-primary-400 hover:text-primary-300 transition-colors inline-flex items-center gap-1 text-sm"
>
Download
</a>
) : (
<span className="text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" title="Invoice not available">
Unavailable
</span>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate payment.invoiceUrl before rendering it as a link.

On Line 334, href is populated directly from API data. If a non-HTTPS or malformed URL is returned, this can create a client-side security risk. Gate the link behind strict URL validation and show “Unavailable” when invalid.

🔒 Suggested fix
+  const getSafeInvoiceUrl = (rawUrl?: string) => {
+    if (!rawUrl) return null;
+    try {
+      const parsed = new URL(rawUrl);
+      return parsed.protocol === 'https:' ? parsed.toString() : null;
+    } catch {
+      return null;
+    }
+  };
...
-                                {payment.invoiceUrl ? (
+                                {getSafeInvoiceUrl(payment.invoiceUrl) ? (
                                   <a
-                                    href={payment.invoiceUrl}
+                                    href={getSafeInvoiceUrl(payment.invoiceUrl)!}
                                     target="_blank"
                                     rel="noopener noreferrer"
                                     className="text-primary-400 hover:text-primary-300 transition-colors inline-flex items-center gap-1 text-sm"
                                   >
                                     Download
                                   </a>
                                 ) : (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Billing.tsx` around lines 332 - 345, Validate
payment.invoiceUrl before rendering the anchor: implement or call a helper
(e.g., isValidInvoiceUrl) that attempts to construct a URL object from
payment.invoiceUrl and ensures url.protocol === 'https:' (reject malformed or
non-HTTPS URLs), then render the <a> only when that validation passes and fall
back to the "Unavailable" <span> otherwise; update the conditional around
payment.invoiceUrl in the Billing component to use that validation check.

Comment on lines +342 to +343
<span className="text-neutral-600 cursor-not-allowed inline-flex items-center gap-1 text-sm" title="Invoice not available">
Unavailable
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

CI is currently blocked by formatting issues.

Pipeline already reports Prettier failure; please run Prettier on this file before merge (the JSX wrapping around these changed lines is a likely contributor).

Also applies to: 379-380

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/Billing.tsx` around lines 342 - 343, Prettier formatting is
failing in the Billing component around the JSX that renders the "Unavailable"
span; run Prettier on src/components/Billing.tsx to reformat the JSX (the span
with className "text-neutral-600 cursor-not-allowed inline-flex items-center
gap-1 text-sm" and the surrounding JSX blocks around lines where "Unavailable"
appears, and the similar JSX near lines 379-380) so the file conforms to project
Prettier rules and the CI pipeline will pass.

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

Labels

type:feature New feature type:refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants