Skip to content

Conversation

@CloudM22
Copy link
Collaborator

@CloudM22 CloudM22 commented Jan 16, 2026

Fixes #100

Summary by CodeRabbit

  • New Features
    • Added a new Buy Credits modal dialog for purchasing credits with flexible amounts (5-100 range).
    • Includes pricing summary showing subtotal, estimated taxes, and total cost.
    • Accessible Buy button to complete the purchase flow.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 16, 2026

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

Project Deployment Review Updated (UTC)
thinkthroo-github-app Ready Ready Preview, Comment Jan 16, 2026 3:26pm
thinkthroo-platform Ready Ready Preview, Comment Jan 16, 2026 3:26pm
thinkthroo-www Ready Ready Preview, Comment Jan 16, 2026 3:26pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

This PR introduces a new BuyCreditsModal component that enables users to purchase credits through a dialog interface. The modal includes credit amount input, tax calculation at 18%, and a purchase button. The component is integrated into the tokens-usage component, replacing an upgrade button with a buy credits button that triggers the modal.

Changes

Cohort / File(s) Summary
New Buy Credits Modal
apps/platform/components/buy-credits-modal.tsx
New exported component providing modal UI for credit purchases. Manages state for credit amount (min 5, max 100, default 25) and autoReload toggle. Displays input field, tax summary (18% of credits), and total cost calculation. Includes full-width buy button and credit terms footer note.
Modal Integration
apps/platform/components/tokens-usage.tsx
Adds useState hook to manage modal open state. Imports and renders BuyCreditsModal component. Replaces previous upgrade button with "Buy Credits" button that opens the modal via onClick handler.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A modal hops in with credits so grand,
Tax at eighteen percent, perfectly planned,
Input your amount, from five up to one-oh-oh,
A button to buy when you're ready to go! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Without detailed requirements in linked issue #100, assessment cannot verify if implementation meets all specified objectives. Review the detailed requirements in issue #100 to confirm the modal implementation includes all required features and functionality.
✅ 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 'Add Buy Credits modal (#100)' clearly and concisely describes the main change: introduction of a new modal component for purchasing credits.
Out of Scope Changes check ✅ Passed All changes (new BuyCreditsModal component and tokens-usage integration) are directly related to implementing the buy credits modal feature.

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

✨ 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

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

Copy link

@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

🤖 Fix all issues with AI agents
In `@apps/platform/components/buy-credits-modal.tsx`:
- Around line 34-35: The close button in buy-credits-modal.tsx is rendered empty
and lacks an accessible name; update the button that calls onOpenChange(false)
to include a visible label and accessible name (e.g., add text "Close" or a
visible icon plus a visually hidden "Close" text), or set aria-label="Close" on
the button; if you use an icon component make it aria-hidden and include the
screen-reader-only text so screen readers get the control name while sighted
users see the icon.
- Around line 40-47: The label for the Credits input in BuyCreditsModal is not
associated with the input, harming accessibility; add an id (e.g.,
"credits-input") to the Input component and set the label's htmlFor to that id
(ensure the Input component accepts and forwards the id prop so the native input
receives it) so clicking the label focuses the number input.
- Around line 41-47: The numeric input handler for the Input component currently
sets credits directly from e.target.value which can become NaN or outside the
allowed [5,100] range; update the onChange (or extract to a handler used by
Input) to parse the value, guard against NaN, clamp it to the min (5) and max
(100), and then call setCredits with the validated/clamped number so credits and
any derived totals remain valid (refer to the Input component usage and the
credits and setCredits state variables).
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 686d96f and 2c81a7a.

📒 Files selected for processing (2)
  • apps/platform/components/buy-credits-modal.tsx
  • apps/platform/components/tokens-usage.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
apps/platform/components/tokens-usage.tsx (2)
packages/ui/src/components/card.tsx (4)
  • CardHeader (86-86)
  • CardTitle (88-88)
  • CardDescription (90-90)
  • CardContent (91-91)
apps/platform/components/buy-credits-modal.tsx (1)
  • BuyCreditsModal (15-80)
🔇 Additional comments (2)
apps/platform/components/buy-credits-modal.tsx (1)

70-76: CTA/terms copy looks solid.

apps/platform/components/tokens-usage.tsx (1)

14-57: Clean modal wiring and CTA integration.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +34 to +35
<button onClick={() => onOpenChange(false)}>
</button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a visible, accessible close control.

The close button renders with no content or accessible name, so it’s effectively invisible to users and screen readers.

🩹 Proposed fix
-            <button onClick={() => onOpenChange(false)}>
-            </button>
+            <button
+              type="button"
+              aria-label="Close"
+              onClick={() => onOpenChange(false)}
+            >
+              ×
+            </button>
📝 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
<button onClick={() => onOpenChange(false)}>
</button>
<button
type="button"
aria-label="Close"
onClick={() => onOpenChange(false)}
>
×
</button>
🤖 Prompt for AI Agents
In `@apps/platform/components/buy-credits-modal.tsx` around lines 34 - 35, The
close button in buy-credits-modal.tsx is rendered empty and lacks an accessible
name; update the button that calls onOpenChange(false) to include a visible
label and accessible name (e.g., add text "Close" or a visible icon plus a
visually hidden "Close" text), or set aria-label="Close" on the button; if you
use an icon component make it aria-hidden and include the screen-reader-only
text so screen readers get the control name while sighted users see the icon.

Comment on lines +40 to +47
<label className="text-sm font-medium">Credits</label>
<Input
type="number"
min={5}
max={100}
value={credits}
onChange={(e) => setCredits(Number(e.target.value))}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Associate the Credits label with the input.

The label isn’t wired to the input, which harms accessibility.

🩹 Proposed fix
-          <label className="text-sm font-medium">Credits</label>
+          <label htmlFor="buy-credits-amount" className="text-sm font-medium">
+            Credits
+          </label>
           <Input
+            id="buy-credits-amount"
             type="number"
             min={5}
             max={100}
             value={credits}
             onChange={(e) => setCredits(Number(e.target.value))}
           />
📝 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
<label className="text-sm font-medium">Credits</label>
<Input
type="number"
min={5}
max={100}
value={credits}
onChange={(e) => setCredits(Number(e.target.value))}
/>
<label htmlFor="buy-credits-amount" className="text-sm font-medium">
Credits
</label>
<Input
id="buy-credits-amount"
type="number"
min={5}
max={100}
value={credits}
onChange={(e) => setCredits(Number(e.target.value))}
/>
🤖 Prompt for AI Agents
In `@apps/platform/components/buy-credits-modal.tsx` around lines 40 - 47, The
label for the Credits input in BuyCreditsModal is not associated with the input,
harming accessibility; add an id (e.g., "credits-input") to the Input component
and set the label's htmlFor to that id (ensure the Input component accepts and
forwards the id prop so the native input receives it) so clicking the label
focuses the number input.

Comment on lines +41 to +47
<Input
type="number"
min={5}
max={100}
value={credits}
onChange={(e) => setCredits(Number(e.target.value))}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clamp and validate credit input to the allowed range.

Min/max on <input type="number"> doesn’t prevent out-of-range or NaN values from entering state, so totals can become invalid.

🧮 Proposed fix
-  const [credits, setCredits] = useState(25)
+  const MIN_CREDITS = 5
+  const MAX_CREDITS = 100
+  const [credits, setCredits] = useState(25)

+  const clampCredits = (value: number) =>
+    Math.min(MAX_CREDITS, Math.max(MIN_CREDITS, value))
...
           <Input
             type="number"
-            min={5}
-            max={100}
+            min={MIN_CREDITS}
+            max={MAX_CREDITS}
             value={credits}
-            onChange={(e) => setCredits(Number(e.target.value))}
+            onChange={(e) => {
+              const next = e.currentTarget.valueAsNumber
+              if (Number.isNaN(next)) return
+              setCredits(clampCredits(next))
+            }}
           />
🤖 Prompt for AI Agents
In `@apps/platform/components/buy-credits-modal.tsx` around lines 41 - 47, The
numeric input handler for the Input component currently sets credits directly
from e.target.value which can become NaN or outside the allowed [5,100] range;
update the onChange (or extract to a handler used by Input) to parse the value,
guard against NaN, clamp it to the min (5) and max (100), and then call
setCredits with the validated/clamped number so credits and any derived totals
remain valid (refer to the Input component usage and the credits and setCredits
state variables).

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.

buy credits modal

3 participants