Skip to content

Conversation

@atticusofsparta
Copy link
Contributor

@atticusofsparta atticusofsparta commented Apr 1, 2025

image

Summary by CodeRabbit

  • New Features

    • Introduced a streamlined checkout process within registration, featuring interactive payment options, an order summary display, and real-time countdown timers.
    • Launched dynamic UI components such as informative tooltips, domain checkout cards, a new checkout component, and a payment options form to enrich the interface.
    • Added new hooks for managing user balances and countdowns.
    • Incorporated new libraries to enhance functionality.
  • Bug Fixes

    • Improved error handling for balance checks and loading states during the checkout process.
  • Style

    • Enhanced text rendering and layout consistency in progress indicators and counters.
    • Expanded the color palette to include a transparent option and new link states for greater design flexibility.

@atticusofsparta atticusofsparta requested a review from a team as a code owner April 1, 2025 06:27
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 1, 2025

Walkthrough

The changes introduce new dependencies, UI components, custom hooks, and styling updates. A new checkout route has been added, along with components for registration checkout, tooltips, domain checkout display, and payment options. New hooks manage token balances, cost details, and countdown functionality, while an older balance hook is removed. Additionally, minor adjustments to component rendering and CSS styling are implemented, and the Tailwind color palette is extended.

Changes

File(s) Change Summary
package.json Added dependencies: dayjs@^1.11.13 and radix-ui@^1.1.3.
src/App.tsx, src/components/pages/Register/Register.tsx, src/components/pages/Register/Checkout.tsx Introduced a new checkout route for registration; added the Checkout component and updated navigation paths.
src/components/Tooltips/ANTDetailsTip.tsx, src/components/cards/DomainCheckoutCard.tsx, src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx New UI components added for tooltips, domain checkout information, and payment options handling.
src/components/icons/index.ts Added icon components: ArIOTokenIcon, ArNSLogo, TurboIcon and JSON data TurboJson.
src/components/inputs/Counter/Counter.tsx, src/components/layout/progress/StepProgressBar/styles.css Updated rendering of valueName using <span class="whitespace-nowrap"> and applied CSS white-space rules to prevent text wrapping.
src/hooks/useArIOBalance.tsx, src/hooks/useCostDetails.tsx, src/hooks/useCountdown.ts Added new hooks to manage liquid/staked balances, cost details (with a constant for stale time), and countdown functionality.
src/hooks/useBalance.tsx Removed outdated custom hook for balance retrieval.
src/utils/constants.ts, tailwind.config.mjs Added a new constant DEFAULT_ANT_LOGO and introduced a transparent color option to Tailwind configuration.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant R as Router
    participant C as Checkout Component
    participant DCC as DomainCheckoutCard
    participant POF as PaymentOptionsForm
    participant HB as Balance Hooks

    U->>R: Navigate to /register/:name/checkout
    R->>C: Render Checkout component
    C->>DCC: Display domain checkout details
    C->>POF: Render payment options form
    POF->>HB: Fetch token balance data
    HB-->>POF: Return balance information
    U->>C: Trigger payment process
    C-->>U: Process payment and update status
Loading

Poem

I'm a rabbit hopping through code so bright,
With routes and hooks that make things light 🐇.
New components bloom in every file,
Guiding users with a seamless style.
I nibble on changes with joyful cheer,
Celebrating fresh code far and near!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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
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

🧹 Nitpick comments (12)
src/App.tsx (1)

318-329: Added new checkout route for domain registration

The new route properly follows the application's established routing pattern and correctly implements the Suspense fallback with PageLoader. This route enables the new domain-specific checkout flow.

Consider adding breadcrumb navigation support to this route, similar to other routes in the application, to maintain navigation consistency.

<Route
  path="register/:name/checkout"
  element={
    <Suspense
      fallback={
        <PageLoader loading={true} message={'Loading, please wait'} />
      }
    >
      <Checkout />
    </Suspense>
  }
+ handle={{
+   crumbs: (data: string) => [
+     { name: 'Register', route: '/' },
+     { name: data, route: `/register/${data}` },
+     { name: 'Checkout', route: `/register/${data}/checkout` },
+   ],
+ }}
/>
src/components/Tooltips/ANTDetailsTip.tsx (2)

1-8: Consider adding component documentation

Adding JSDoc comments would help explain the purpose of this component to other developers.

+/**
+ * A tooltip component that displays ANT (Arweave Name Token) details including process ID, target ID, and owner.
+ * Validates and formats Arweave transaction IDs, providing clickable links to explore them.
+ */
 function ANTDetailsTip({

30-71: Consider extracting repeated patterns into a reusable component

The tooltip contains three nearly identical sections with only minor differences. Consider extracting this pattern into a reusable component to reduce duplication.

+// Add to the top of the file
+function DetailRow({ label, id, type }: { label: string; id?: string; type?: ArweaveIdTypes }) {
+  return (
+    <span className="flex gap-2 text-sm text-grey py-4 border-b-[1px] border-dark-grey whitespace-nowrap gap-2">
+      {label}:{' '}
+      {isArweaveTransactionID(id) ? (
+        <ArweaveID
+          id={new ArweaveTransactionID(id)}
+          shouldLink={true}
+          characterCount={16}
+          type={type}
+        />
+      ) : (
+        type === ArweaveIdTypes.ADDRESS ? formatForMaxCharCount(id ?? 'N/A', 16) : 'N/A'
+      )}
+    </span>
+  );
+}

// Then in the component
-<div className="flex flex-col p-2">
-  <span className="flex gap-2 text-sm text-grey py-4 border-b-[1px] border-dark-grey whitespace-nowrap gap-2">
-    Process ID:{' '}
-    {isArweaveTransactionID(antId) ? (
-      <ArweaveID
-        id={new ArweaveTransactionID(antId)}
-        shouldLink={true}
-        characterCount={16}
-        type={ArweaveIdTypes.CONTRACT}
-      />
-    ) : (
-      'N/A'
-    )}
-  </span>
-
-  <span className="flex gap-2 text-sm text-grey py-4 border-b-[1px] border-dark-grey whitespace-nowrap">
-    Target ID:{' '}
-    {isArweaveTransactionID(targetId) ? (
-      <ArweaveID
-        id={new ArweaveTransactionID(targetId)}
-        shouldLink={true}
-        characterCount={16}
-        type={ArweaveIdTypes.TRANSACTION}
-      />
-    ) : (
-      'N/A'
-    )}
-  </span>
-  <span className="flex gap-2 text-sm text-grey py-4 border-b-[1px] border-dark-grey whitespace-nowrap">
-    Owner:{' '}
-    {isArweaveTransactionID(owner) ? (
-      <ArweaveID
-        id={new ArweaveTransactionID(owner)}
-        shouldLink={true}
-        characterCount={16}
-        type={ArweaveIdTypes.ADDRESS}
-      />
-    ) : (
-      formatForMaxCharCount(owner ?? 'N/A', 16)
-    )}
-  </span>
+<div className="flex flex-col p-2">
+  <DetailRow label="Process ID" id={antId} type={ArweaveIdTypes.CONTRACT} />
+  <DetailRow label="Target ID" id={targetId} type={ArweaveIdTypes.TRANSACTION} />
+  <DetailRow label="Owner" id={owner} type={ArweaveIdTypes.ADDRESS} />
</div>
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (3)

40-64: Ensure proper calculation of token balances

The balance calculations use useMemo correctly, but selectedCryptoBalance should also directly depend on the individual balance variables for better consistency.

const selectedCryptoBalance = useMemo(() => {
  if (selectedCrypto === '$ARIO') {
-    return allArIOBalance;
+    return fundingSource === 'balance' 
+      ? liquidArIOBalance 
+      : fundingSource === 'stakes' 
+        ? stakedAndVaultedArIOBalance 
+        : allArIOBalance;
  }
  return 0;
-}, [selectedCrypto, allArIOBalance]);
+}, [selectedCrypto, allArIOBalance, liquidArIOBalance, stakedAndVaultedArIOBalance, fundingSource]);

110-111: Enhance "Coming Soon" messaging

The "Coming Soon!" messages for credit card and credits payment methods could provide more context to users about when these features might be available or offer an alternative payment method.

- <span className="text-grey flex m-auto">Coming Soon!</span>
+ <div className="flex flex-col items-center justify-center gap-2 m-auto text-center">
+   <span className="text-grey">Coming Soon!</span>
+   <span className="text-xs text-grey/70">This payment method will be available in a future update.</span>
+   <span className="text-xs text-grey/70">Please use the Crypto option for now.</span>
+ </div>

Also applies to: 204-205


37-39: Add loading states for balance fetching

The component could benefit from showing loading states when fetching balances to provide better user feedback.

-  const { data: liquidBalance } = useArIOLiquidBalance();
-  const { data: stakedAndVaultedBalance } = useArIOStakedAndVaultedBalance();
+  const { data: liquidBalance, isLoading: isLiquidLoading } = useArIOLiquidBalance();
+  const { 
+    data: stakedAndVaultedBalance, 
+    isLoading: isStakedLoading 
+  } = useArIOStakedAndVaultedBalance();
+  const isBalanceLoading = isLiquidLoading || isStakedLoading;

// Then in the balance display section:
<span className="text-white text-2xl font-bold">
-  {formatARIOWithCommas(selectedCryptoBalance)} {selectedCrypto}
+  {isBalanceLoading 
+    ? <span className="text-grey animate-pulse">Loading...</span>
+    : `${formatARIOWithCommas(selectedCryptoBalance)} ${selectedCrypto}`
+  }
</span>
src/hooks/useCountdown.ts (2)

15-57: Add protection against invalid timestamps

The hook should handle cases where the provided timestamp is invalid.

useEffect(() => {
+  // Return early if timestamp is invalid
+  if (!endTimestamp || isNaN(endTimestamp) || endTimestamp <= 0) {
+    setCountdownString(null);
+    return;
+  }

  const interval = setInterval(() => {

36-53: Extract formatting logic into a separate function

The countdown formatting logic is complex and would benefit from being extracted into a separate function for better readability and testability.

+ // Add this function outside the hook or inside but before useEffect
+ function formatCountdown(duration: Duration): string {
+   const years = duration.years();
+   const months = duration.months();
+   const weeks = Math.floor(duration.days() / 7);
+   const days = duration.days() % 7;
+   const hours = duration.hours();
+   const minutes = duration.minutes();
+   const seconds = duration.seconds();
+
+   // Format based on the largest unit present
+   if (years > 0) {
+     return `${years}y ${months}m`;
+   } else if (months > 0) {
+     return `${months}m ${weeks}w`;
+   } else if (weeks > 0) {
+     return `${weeks}w ${days}d`;
+   } else if (days > 0) {
+     return `${days}d ${hours}h`;
+   } else if (hours > 0) {
+     return `${hours}:${minutes < 10 ? `0${minutes}` : minutes}`;
+   } else {
+     return `${minutes}:${seconds < 10 ? `0${seconds}` : seconds}`;
+   }
+ }

// Then in the useEffect
const duration = dayjs.duration(diff);
- const years = duration.years();
- const months = duration.months();
- const weeks = Math.floor(duration.days() / 7);
- const days = duration.days() % 7;
- const hours = duration.hours();
- const minutes = duration.minutes();
- const seconds = duration.seconds();
-
- // Format based on the largest unit present
- if (years > 0) {
-   setCountdownString(`${years}y ${months}m`);
- } else if (months > 0) {
-   setCountdownString(`${months}m ${weeks}w`);
- } else if (weeks > 0) {
-   setCountdownString(`${weeks}w ${days}d`);
- } else if (days > 0) {
-   setCountdownString(`${days}d ${hours}h`);
- } else if (hours > 0) {
-   setCountdownString(
-     `${hours}:${minutes < 10 ? `0${minutes}` : minutes}`,
-   );
- } else {
-   setCountdownString(
-     `${minutes}:${seconds < 10 ? `0${seconds}` : seconds}`,
-   );
- }
+ setCountdownString(formatCountdown(duration));
src/components/cards/DomainCheckoutCard.tsx (2)

41-44: Consider extracting these color references into the Tailwind config or constants.
Centralizing color definitions (e.g., #[FEC35F] and #[EEA5D2]) helps maintain consistency across the app and makes it simpler to update branding later.


1-160: Add a basic unit test to validate the domain, fee, and countdown rendering logic.
This new component is key to the checkout flow. A short test suite can ensure future refactors don’t break expected behavior. You can use React Testing Library to confirm that fees and countdown strings display as intended.

Do you want me to generate an initial test sample? I can open a new issue if you’d like to track this.

src/hooks/useArIOBalance.tsx (1)

38-53: Consider adding a maximum iteration limit or partial results strategy for large delegations.
The while loop can potentially run numerous times if the user’s delegations are very large. Adding a limit or loading progressively can improve responsiveness and reduce heavy calls in extreme cases.

src/components/pages/Register/Checkout.tsx (1)

69-73: Simplify the boolean expression in the ternary.
Using a direct boolean cast is more concise and clearer:

- return costDetail?.fundingPlan?.shortfall ? true : false;
+ return !!costDetail?.fundingPlan?.shortfall;
🧰 Tools
🪛 Biome (1.9.4)

[error] 70-70: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 422eae2 and f48a83c.

⛔ Files ignored due to path filters (5)
  • assets/images/logo/arns-logo.svg is excluded by !**/*.svg
  • src/components/icons/ArIOTokenIcon.svg is excluded by !**/*.svg
  • src/components/icons/ArNSLogo.svg is excluded by !**/*.svg
  • src/components/icons/TurboIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (16)
  • package.json (2 hunks)
  • src/App.tsx (2 hunks)
  • src/components/Tooltips/ANTDetailsTip.tsx (1 hunks)
  • src/components/cards/DomainCheckoutCard.tsx (1 hunks)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
  • src/components/icons/index.ts (4 hunks)
  • src/components/inputs/Counter/Counter.tsx (1 hunks)
  • src/components/layout/progress/StepProgressBar/styles.css (3 hunks)
  • src/components/pages/Register/Checkout.tsx (1 hunks)
  • src/components/pages/Register/Register.tsx (1 hunks)
  • src/hooks/useArIOBalance.tsx (1 hunks)
  • src/hooks/useBalance.tsx (0 hunks)
  • src/hooks/useCostDetails.tsx (2 hunks)
  • src/hooks/useCountdown.ts (1 hunks)
  • src/utils/constants.ts (1 hunks)
  • tailwind.config.mjs (1 hunks)
💤 Files with no reviewable changes (1)
  • src/hooks/useBalance.tsx
🧰 Additional context used
🧬 Code Definitions (3)
src/App.tsx (1)
src/utils/routes.tsx (1)
  • Route (15-23)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
src/components/icons/index.ts (3)
  • ArIOTokenIcon (74-74)
  • TurboIcon (133-133)
  • CircleCheck (93-93)
src/components/pages/Register/Checkout.tsx (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
  • PaymentMethod (13-13)
🪛 Biome (1.9.4)
src/components/pages/Register/Checkout.tsx

[error] 70-70: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_and_test / lint_test_build
🔇 Additional comments (18)
src/utils/constants.ts (1)

96-96: LGTM! New constant for default ANT logo.

The addition of the DEFAULT_ANT_LOGO constant follows the project's naming convention and will likely be used in the new domain checkout UI components.

tailwind.config.mjs (1)

52-52: LGTM! Adding transparent color to Tailwind config.

Adding the transparent color explicitly to the configuration makes it more discoverable and ensures consistency in the project's color system.

package.json (2)

45-45: LGTM! Adding dayjs dependency.

Adding dayjs is appropriate for the new countdown functionality required in the checkout feature.


55-55:

❓ Verification inconclusive

Verify if base radix-ui package is needed.

The project already uses specific Radix UI component packages (e.g., @radix-ui/react-radio-group). Adding the base radix-ui package is unusual - typically you would add specific component packages as needed.


🏁 Script executed:

#!/bin/bash
# Check if radix-ui is imported anywhere in the codebase
rg -i "from ['\"]radix-ui['\"]" || echo "No direct imports of radix-ui found"

# Check which specific Radix UI packages are already imported
rg -i "from ['\"]@radix-ui/react-" | sort | uniq

Length of output: 458


Action: Confirm Necessity of the Base radix-ui Dependency

  • Observation:

    • The file src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx imports { Tabs } from the base radix-ui package.
    • Other components consistently import specific Radix UI packages (e.g., @radix-ui/react-radio-group, @radix-ui/react-select, @radix-ui/react-switch).
  • Suggestion:

    • Verify if importing Tabs directly from radix-ui is intentional.
    • If a dedicated package (such as @radix-ui/react-tabs) exists, consider refactoring the import in PaymentOptionsForm.tsx for consistency and clearer dependency management.
    • Otherwise, if the base package is required for additional functionality, please confirm its necessity and ensure that its usage aligns with the current design approach.
src/hooks/useCostDetails.tsx (1)

10-10: LGTM! Extracted stale time to a named constant.

Good refactoring to improve code maintainability by extracting the hardcoded stale time value into a named constant. This makes the code more readable and easier to modify in the future.

Also applies to: 25-25

src/components/layout/progress/StepProgressBar/styles.css (3)

39-39: Improved step descriptions layout with white-space: nowrap

Adding white-space: nowrap ensures the description text in completed steps stays on a single line, preventing awkward text wrapping that could disrupt the layout of the progress bar in the new checkout flow.


65-65: Consistent text wrapping behavior for active step

Good addition of white-space: nowrap to maintain layout consistency with the current step's description, matching the styling applied to completed steps.


91-91: Completed the consistent styling across all step states

This completes the consistent application of white-space: nowrap to waiting steps, ensuring uniform text layout behavior across all three states of the progress bar (completed, active, and waiting).

src/components/pages/Register/Register.tsx (1)

189-189:

❓ Verification inconclusive

Updated navigation path to new checkout flow

The navigation path has been correctly updated to point to the new domain-specific checkout page instead of the generic transaction review page, aligning with the new checkout feature being implemented.


🏁 Script executed:

#!/bin/bash
# Verify that there are no other places still using the old transaction review path for domain registration
rg -A 1 -B 1 "navigate\(\`/transaction/review\`" --type ts | grep -v "//.*navigate"

Length of output: 83


Navigation Path Update Verified and Approved

The navigation in src/components/pages/Register/Register.tsx (line 189) is now correctly updated to the new domain-specific checkout page (/register/${domain}/checkout). An initial repository-wide search for references to the deprecated /transaction/review path returned no results. However, since the original verification output was ambiguous, please perform a manual review or run an additional check to confirm that no lingering references to the old transaction review path exist.

  • Updated navigation path correctly targets the new checkout flow.
  • No instances of the old /transaction/review path were detected, but manual re-verification is advised.
src/components/inputs/Counter/Counter.tsx (1)

102-106: Enhanced value and unit display with whitespace-nowrap

The change wraps the value and its unit (like "years") in a span with the whitespace-nowrap class, ensuring they always appear together on the same line. This improves visual consistency in the checkout process when displaying registration periods.

src/App.tsx (1)

15-15: Added import for new Checkout component

Added the necessary import for the Checkout component to support the new checkout route.

src/components/icons/index.ts (1)

6-7: New icons look good!

The newly added icons (ArIOTokenIcon, ArNSLogo, TurboIcon) and TurboJson asset are properly imported and exported. These additions align well with the checkout feature being implemented.

Also applies to: 58-58, 67-67, 70-70, 74-74, 133-134

src/components/Tooltips/ANTDetailsTip.tsx (1)

9-76: LGTM: Well-implemented tooltip component for ANT details

The component correctly displays ANT details with proper validation using isArweaveTransactionID and fallbacks to "N/A" when values are missing or invalid.

src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (2)

1-36: Well-structured payment form implementation

The PaymentOptionsForm component is well-structured with clear types, component organization, and state management for different payment methods and funding sources.


65-209: Clean UI implementation with appropriate user options

The UI implementation provides a clear interface for users to select payment methods and funding sources with appropriate visual feedback.

src/hooks/useCountdown.ts (1)

7-60: Well-implemented countdown hook with clean formatting logic

The useCountdown hook provides a nice abstraction for creating countdown timers with appropriate cleanup and format handling.

src/components/cards/DomainCheckoutCard.tsx (1)

57-63: Validate or sanitize domain input to avoid malformed URLs in the link.
If domain might be user-provided or derived from external inputs, ensure it’s validated or sanitized to prevent user-experience issues or potential vulnerabilities (e.g., accidental or malicious injection of extra path segments).

Would you like help creating a basic validation utility?

src/components/pages/Register/Checkout.tsx (1)

48-51: Clarify or implement the 'card' and 'credits' payment methods.
Currently, the code defaults to 'crypto', and non-crypto methods are marked as always insufficient. Consider adding a placeholder flow or separate logic for 'card' and 'credits' if they’ll be supported soon.

Would you like me to open a follow-up PR or create an issue to track this?

@github-actions
Copy link

github-actions bot commented Apr 1, 2025

Visit the preview URL for this PR (updated for commit caac677):

https://arns-portal--pr731-pe-7854-payments-exdfgkfn.web.app

(expires Thu, 17 Apr 2025 18:38:50 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 1f59769442cb89cf2a92042a342e51fe94047b94

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

🧹 Nitpick comments (8)
src/components/cards/DomainCheckoutCard.tsx (8)

34-37: Consider adding error handling for domain info fetching.

The component fetches domain information but doesn't handle potential loading or error states from the useDomainInfo hook. This could lead to undefined property access later in the component.

- const { data: domainInfo } = useDomainInfo({
+ const { data: domainInfo, isLoading, error } = useDomainInfo({
    antId: isArweaveTransactionID(antId) ? antId : undefined,
  });

+ // Display loading state or error message if needed
+ if (isLoading) {
+   // Consider adding a loading indicator
+ }
+ 
+ if (error) {
+   // Consider handling error state
+ }

46-52: Ensure fallback handling for AntLogoIcon.

Good use of conditional rendering for the logo based on whether antId is a valid Arweave transaction ID. However, there's no explicit handling if domainInfo is undefined or null when accessing the nested property.

<AntLogoIcon
  id={
    isArweaveTransactionID(antId)
-     ? domainInfo?.logo
+     ? domainInfo?.logo || DEFAULT_ANT_LOGO
      : DEFAULT_ANT_LOGO
  }
/>

54-55: Remove unnecessary whitespace elements.

There are several instances of {' '} in the JSX which add extra whitespace. These can often be removed without affecting the layout, or handled with CSS margin/padding instead.

<div className="flex items-center w-fit ">
-   {' '}
    <Link
<span className="text-white max-w-[180px] truncate">
-   {' '}
    {domain}
</span>
-   </div>{' '}
+   </div>

Also applies to: 77-78, 81-81


90-91: Tailwind class optimization opportunity.

The size-full class (which sets both width and height to 100%) is used alongside flex-col, but may be redundant since the parent already controls the sizing.

<div
- className={`flex flex-col border-y-[1px] border-foreground gap-4 mt-8 py-6 size-full z-10`}
+ className={`flex flex-col border-y-[1px] border-foreground gap-4 mt-8 py-6 w-full z-10`}
>

98-105: Consider adding empty state handling for order summary.

The component maps over orderSummary entries but doesn't handle the case where it might be empty. Consider adding a fallback message when there are no items to display.

- {Object.entries(orderSummary).map(([key, value], i) => (
+ {Object.entries(orderSummary).length > 0 ? Object.entries(orderSummary).map(([key, value], i) => (
  <div className="flex flex-row w-full text-sm" key={i}>
    <span className="flex w-1/3 whitespace-nowrap text-grey">
      {key}
    </span>
    <span className="flex w-1/2 whitespace-nowrap">{value}</span>
  </div>
- ))}
+ )) : (
+   <div className="text-grey">No order details available</div>
+ )}

108-108: Remove unnecessary space comment.

There's an unnecessary {' '} after the closing div that can be removed.

- </div>{' '}
+ </div>

142-152: Fix cursor pointer styling in refresh button.

The class "pointer" is used, but in Tailwind CSS the correct class is "cursor-pointer".

<button
  onClick={refresh}
- className="flex gap-2 items-center justify-center text-center text-grey pointer"
+ className="flex gap-2 items-center justify-center text-center text-grey cursor-pointer"
>

41-156: Consider adding accessibility improvements.

The component could benefit from additional accessibility attributes. Consider adding appropriate ARIA labels to interactive elements and ensuring all UI elements have sufficient contrast.

For the refresh button, add an aria-label:

<button
  onClick={refresh}
+ aria-label="Refresh quote"
  className="flex gap-2 items-center justify-center text-center text-grey pointer"
>

For the quote status, consider adding aria-live for screen readers:

- <span>
+ <span aria-live="polite">
  {quoteEndTimestamp < 0 ? (
    <span className="text-error">Error fetching quote</span>
  ) : countdownString ? (
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f48a83c and 69d88b4.

📒 Files selected for processing (3)
  • src/components/cards/DomainCheckoutCard.tsx (1 hunks)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
  • src/components/pages/Register/Register.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/components/pages/Register/Register.tsx
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build_and_test / lint_test_build
🔇 Additional comments (5)
src/components/cards/DomainCheckoutCard.tsx (5)

1-14: Good organization of imports and clean dependency structure.

The imports are well-organized and logical, separating custom hooks, utilities, constants, and UI components. Good practice to use absolute imports with @src prefix for project files.


15-23: Well-defined prop interface with appropriate optionality.

The DomainCheckoutCardProps type is clearly defined with proper JSDoc comments. You've correctly marked optional props with the ? operator.


39-39: Verify countdown behavior when timestamp expires.

The useCountdown hook is used to display time remaining, but there's no clear handling for what happens after the countdown reaches zero. Ensure the UI updates appropriately when the quote expires.


111-123: Good implementation of fees display section.

The component cleanly iterates through the fees object and displays each fee with proper styling and layout. The use of key={i} is acceptable here since the data structure is stable.


130-140: Well-handled conditional rendering for quote status.

Good implementation of conditional rendering for different quote states (error, countdown, updating). The use of appropriate visual cues (error text color, animation for loading) helps with user experience.

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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 (7)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (7)

57-62: Consider handling all CryptoOptions values

The type CryptoOptions includes $dARIO and $tARIO, but the balance calculation only returns a value for $ARIO.

Since you've defined multiple crypto options in the type, consider handling all cases or adding a comment explaining why only ARIO is supported currently.

  const selectedCryptoBalance = useMemo(() => {
    if (selectedCrypto === formattedARIOTicker) {
      return allArIOBalance;
    }
+   // Other tokens not supported yet, returning 0
+   // TODO: Add support for other tokens when available
    return 0;
  }, [selectedCrypto, allArIOBalance, formattedARIOTicker]);

82-93: Consider extracting repeated tooltip pattern

The tooltips for disabled payment methods follow the same pattern. Consider extracting this to a helper component for better maintainability.

+ const DisabledPaymentOption = ({ icon, label, message = "Coming Soon!" }) => (
+   <Tooltip
+     message={message}
+     icon={
+       <div className="flex gap-3 items-center">
+         {icon}
+         {label}
+       </div>
+     }
+   />
+ );

  <Tabs.Trigger
    value="card"
    disabled={true}
    className="flex gap-3 p-3 data-[state=active]:bg-foreground rounded border border-[#222224] data-[state=active]:border-grey text-white items-center flex-1 whitespace-nowrap transition-all duration-300 disabled:opacity-50"
  >
-   <Tooltip
-     message="Coming Soon!"
-     icon={
-       <div className="flex gap-3 items-center">
-         <CreditCard className="size-5 text-grey" />
-         Credit Card
-       </div>
-     }
-   />
+   <DisabledPaymentOption 
+     icon={<CreditCard className="size-5 text-grey" />}
+     label="Credit Card"
+   />
  </Tabs.Trigger>

Also applies to: 103-118


82-82: Avoid hardcoded color values

Replace hardcoded colors like '#222224' with Tailwind color variables for better maintainability.

For example:

- className="flex gap-3 p-3 data-[state=active]:bg-foreground rounded border border-[#222224] data-[state=active]:border-grey text-white items-center flex-1 whitespace-nowrap transition-all duration-300 disabled:opacity-50"
+ className="flex gap-3 p-3 data-[state=active]:bg-foreground rounded border border-dark-grey data-[state=active]:border-grey text-white items-center flex-1 whitespace-nowrap transition-all duration-300 disabled:opacity-50"

This makes it easier to maintain consistent colors across the application.

Also applies to: 96-96, 104-104, 122-122, 128-128, 139-139, 169-169, 183-183, 198-198, 216-216


122-122: Extract common tab content styles

The className for the tab contents are nearly identical with minor differences. Consider extracting these to a common style variable.

+ const tabContentBaseClass = 
+   "flex flex-col data-[state=active]:border border-dark-grey rounded h-full data-[state=inactive]:size-0 data-[state=inactive]:opacity-0 data-[state=active]:min-h-[405px]";

  <Tabs.Content
    value="card"
-   className={`flex flex-col data-[state=active]:p-4 data-[state=active]:border border-dark-grey rounded h-full data-[state=inactive]:size-0 data-[state=inactive]:opacity-0 data-[state=active]:min-h-[405px]`}
+   className={`${tabContentBaseClass} data-[state=active]:p-4`}
  >

Also applies to: 128-128, 216-216


34-49: Add error handling for balance fetching

The component doesn't visually handle potential errors when fetching balances.

Consider adding error handling to show a user-friendly message when balance fetching fails:

- const { data: liquidBalance } = useArIOLiquidBalance();
- const { data: stakedAndVaultedBalance } = useArIOStakedAndVaultedBalance();
+ const { data: liquidBalance, error: liquidBalanceError } = useArIOLiquidBalance();
+ const { data: stakedAndVaultedBalance, error: stakedBalanceError } = useArIOStakedAndVaultedBalance();

// Later in the render function:
+ {(liquidBalanceError || stakedBalanceError) && (
+   <div className="text-error text-xs mt-1">
+     Error loading balances. Please try again.
+   </div>
+ )}

148-150: Fix token symbol duplication

There's a potential duplication of the $ symbol since selectedCrypto already includes it.

  <span className="text-grey text-xs">
    Your total {selectedCrypto} balance:
  </span>
  <span className="text-white text-2xl font-bold">
-   {formatARIOWithCommas(selectedCryptoBalance)} {selectedCrypto}
+   {formatARIOWithCommas(selectedCryptoBalance)} ARIO
  </span>

Similarly, check lines 179, 195, and 207 where "ARIO" is displayed directly, which is more consistent.


178-179: Ensure consistent spacing in formatted text

The spacing in the formatted text for balances is inconsistent. There are cases where parentheses are adjacent to text without proper spacing.

- <span className="font-bold">Liquid Balance</span> ({formatARIOWithCommas(liquidArIOBalance)} ARIO)
+ <span className="font-bold">Liquid Balance</span> ({formatARIOWithCommas(liquidArIOBalance)} ARIO)

- <span className="font-bold">Liquid + Staked Balances</span>{' '}({formatARIOWithCommas(allArIOBalance)} ARIO)
+ <span className="font-bold">Liquid + Staked Balances</span> ({formatARIOWithCommas(allArIOBalance)} ARIO)

- </span>{' '}<span className="font-bold">Staked Balances</span> ({formatARIOWithCommas(stakedAndVaultedArIOBalance)} ARIO)
+ </span> <span className="font-bold">Staked Balances</span> ({formatARIOWithCommas(stakedAndVaultedArIOBalance)} ARIO)

Be consistent with how whitespace is handled in these lines. The explicit {' '} is unnecessary if spacing can be added directly.

Also applies to: 191-195, 206-207

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 289529f and 2cdd28d.

📒 Files selected for processing (1)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
src/components/icons/index.ts (3)
  • ArIOTokenIcon (74-74)
  • TurboIcon (133-133)
  • CircleCheck (93-93)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy-to-firebase
🔇 Additional comments (6)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (6)

29-33: Using ticker from contract is good

Using arioTicker from global state to create crypto options is the right approach.


37-52: Balance calculations look correct

The balance calculations are well-structured and correctly memoized, with proper handling of undefined values.


1-28: Props and imports look good

The component has well-structured props with appropriate defaults and clear type definitions. The imports are properly organized.


131-143: SelectDropdown implementation is correct

The dropdown implementation for crypto options is well done, with proper value management and styling.


68-119: Tab navigation is well implemented

The payment method tabs are properly set up with clear visual indication of which tab is active and appropriate disabling of future features.


12-12:

✅ Verification successful

Verify Radix UI import path

The import Tabs from 'radix-ui' seems unusual. Typically, Radix UI components are imported from scoped packages like '@radix-ui/react-tabs'.


🏁 Script executed:

#!/bin/bash
# Check for Radix UI package in package.json
grep -r "\"radix-ui\":" package.json
# Check if there are other imports from radix-ui in the codebase
grep -r "from 'radix-ui'" --include="*.tsx" --include="*.ts" src/

Length of output: 232


Radix UI Import Path Verified as Correct

After checking the package.json and the codebase, we confirmed that the project intentionally depends on the "radix-ui" package (version "^1.1.3") and consistently imports from it. No changes are needed regarding the current import path.

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 (5)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (5)

32-34: Consider future-proofing the crypto dropdown options

Currently, the dropdown only offers one option ($ARIO). While this matches current requirements, the component structure suggests you intend to support multiple tokens in the future. You might want to add a TODO comment for clarity.


58-63: Consider adding error states for balance retrieval failures

While the code handles undefined balances by defaulting to 0, it might be helpful to show loading states or error messages when balance retrieval fails.

 const selectedCryptoBalance = useMemo(() => {
   if (selectedCrypto === formattedARIOTicker) {
     return allArIOBalance;
   }
   return 0;
-}, [selectedCrypto, allArIOBalance, formattedARIOTicker]);
+}, [selectedCrypto, allArIOBalance, formattedARIOTicker]);
+
+// Add error handling for balance retrieval failures
+const isLoadingBalance = liquidBalance === undefined || stakedAndVaultedBalance === undefined;

132-144: Consider improving accessibility for crypto dropdown

The dropdown is currently marked with pointer-events-none, which makes it appear disabled but might cause accessibility issues. Since this is the only available option, consider either:

  1. Making it actually functional but with just one option
  2. Displaying the selection as plain text without a dropdown UI
 className={{
   trigger:
-    'flex w-full gap-2 p-3 rounded-md bg-transparent border border-[#222224] items-center pointer-events-none',
+    'flex w-full gap-2 p-3 rounded-md bg-transparent border border-[#222224] items-center',
   icon: 'text-grey size-5',
 }}
 options={cryptoDropdownOptions}

180-180: Use consistent token naming in UI display

There's an inconsistency in how the token is displayed. Some places use "ARIO" and others use the variable selectedCrypto which includes the "$" prefix. Consider using a consistent approach throughout.

-<span className="font-bold">Liquid Balance</span> ({formatARIOWithCommas(liquidArIOBalance)} ARIO)
+<span className="font-bold">Liquid Balance</span> ({formatARIOWithCommas(liquidArIOBalance)} {selectedCrypto.replace('$', '')})

Similar changes should be applied to lines 195-196 and 208-209.

Also applies to: 195-196, 208-209


1-227: Consider adding validation for insufficient balance scenarios

The component displays balances effectively but doesn't appear to have validation for scenarios where the selected funding source has insufficient balance for the purchase. Consider adding this validation to prevent failed transactions.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2cdd28d and 81cb85e.

📒 Files selected for processing (1)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
src/components/icons/index.ts (3)
  • ArIOTokenIcon (74-74)
  • TurboIcon (133-133)
  • CircleCheck (93-93)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy-to-firebase
🔇 Additional comments (4)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (4)

30-31: Use the ticker directly from the contract without manual formatting

The code formats the ticker with a dollar sign prefix before using it. According to a previous review comment, you should use the ticker directly from the contract.


38-53: Good use of useMemo for balance calculations

The balance calculations are appropriately wrapped in useMemo hooks, which prevents unnecessary recalculations during renders.


82-94: Great user experience with tooltips for unavailable options

Using tooltips with "Coming Soon!" messages for disabled payment methods provides good UX by setting clear expectations for future features.


155-213: Well-implemented funding source selection

The funding source selection is well-implemented with clear visual feedback using check icons and informative balance displays. The component correctly updates the parent component through callbacks when selections change.

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

🧹 Nitpick comments (9)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (4)

1-1: Consider adding explicit type definitions for imports.
When using inline imports, it can be helpful to explicitly type them (e.g., import { FundFrom } from '@ar.io/sdk';) to ensure the integration with external libraries is fully typed.


32-34: Handle future expansions of crypto dropdown options.
Using useMemo is efficient here, but if additional tokens end up being introduced, ensure they dynamically refresh the dropdown if new tokens are fetched from an API or global state.


82-83: Double-check disabled state for payment triggers.
Disabling the "card" payment method is an effective placeholder. However, consider conditionally enabling it or completely hiding the tab if development is far off to avoid user confusion.


104-106: Confirm the user flow for crypto vs. credits.
Similar to the "card" method, the "credits" option is also disabled. If these are on a near-term roadmap, it might be clearer to display a short contextual message in plain text instead of a disabled button.

src/components/Tooltips/ANTDetailsTip.tsx (5)

9-21: Props structure looks good, but needs validation for edge cases.

The component has a clear prop structure with appropriate types, making it easy to understand what information should be provided. However, since all props are optional, the component could render with no meaningful information if no props are provided.

Consider adding validation or default content for cases when no valid IDs are provided:

function ANTDetailsTip({
  antId,
  targetId,
  owner,
  icon = (
    <InfoCircleOutlined className="text-grey" width={'14px'} height={'14px'} />
  ),
}: {
  antId?: string;
  targetId?: string;
  owner?: string;
  icon?: ReactNode;
}) {
+  const hasValidData = antId || targetId || owner;
+  if (!hasValidData) {
+    return null; // Or some fallback UI
+  }
  return (
    // ...

13-15: Icon dimensions should use number values instead of strings.

The width and height props should be provided as numbers rather than strings to avoid potential warnings from React.

  icon = (
-    <InfoCircleOutlined className="text-grey" width={'14px'} height={'14px'} />
+    <InfoCircleOutlined className="text-grey" style={{ fontSize: '14px' }} />
  ),

23-28: Consider extracting tooltip styling to dedicated class.

The tooltip configuration uses multiple inline style objects which could be better managed through a dedicated CSS class or Tailwind utility classes.

<Tooltip
-  tooltipOverrides={{
-    overlayClassName: 'flex w-fit',
-    overlayStyle: { width: 'fit-content' },
-    overlayInnerStyle: { width: 'fit-content' },
-  }}
+  tooltipOverrides={{
+    overlayClassName: 'flex w-fit ant-details-tooltip',
+  }}
  message={

Then define the class in your CSS/SCSS file:

.ant-details-tooltip {
  width: fit-content !important;
}
.ant-details-tooltip .ant-tooltip-inner {
  width: fit-content !important;
}

31-43: Inconsistent handling of invalid IDs.

The component handles invalid values differently across the three sections. Process ID and Target ID show 'N/A' when invalid, but Owner uses formatting.

For better consistency:

{isArweaveTransactionID(owner) ? (
  <ArweaveID
    id={new ArweaveTransactionID(owner)}
    shouldLink={true}
    characterCount={16}
    type={ArweaveIdTypes.ADDRESS}
  />
) : (
-  formatForMaxCharCount(owner ?? 'N/A', 16)
+  owner ? formatForMaxCharCount(owner, 16) : 'N/A'
)}

Additionally, consider extracting the repeated pattern into a reusable function to reduce duplication:

const renderArweaveId = (id?: string, type: ArweaveIdTypes) => {
  if (isArweaveTransactionID(id)) {
    return (
      <ArweaveID
        id={new ArweaveTransactionID(id)}
        shouldLink={true}
        characterCount={16}
        type={type}
      />
    );
  }
  return id ? formatForMaxCharCount(id, 16) : 'N/A';
};

Also applies to: 45-57, 58-70


30-71: Extract repeated layout patterns to improve readability.

The component has three similar sections with identical styling and only minor differences in content. This pattern could be extracted to reduce duplication.

Consider creating a helper component for the repeated layout:

type DetailRowProps = {
  label: string;
  value?: string;
  idType?: ArweaveIdTypes;
};

const DetailRow = ({ label, value, idType }: DetailRowProps) => (
  <span className="flex gap-2 text-sm text-grey py-4 border-b-[1px] border-dark-grey whitespace-nowrap">
    {label}:{' '}
    {isArweaveTransactionID(value) && idType ? (
      <ArweaveID
        id={new ArweaveTransactionID(value)}
        shouldLink={true}
        characterCount={16}
        type={idType}
      />
    ) : (
      value ? formatForMaxCharCount(value, 16) : 'N/A'
    )}
  </span>
);

// Then in the component:
<div className="flex flex-col p-2 pt-0">
  <DetailRow label="Process ID" value={antId} idType={ArweaveIdTypes.CONTRACT} />
  <DetailRow label="Target ID" value={targetId} idType={ArweaveIdTypes.TRANSACTION} />
  <DetailRow label="Owner" value={owner} idType={ArweaveIdTypes.ADDRESS} />
</div>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 81cb85e and 814689d.

📒 Files selected for processing (2)
  • src/components/Tooltips/ANTDetailsTip.tsx (1 hunks)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
src/components/icons/index.ts (3)
  • ArIOTokenIcon (74-74)
  • TurboIcon (133-133)
  • CircleCheck (93-93)
🔇 Additional comments (3)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (2)

15-17: Validate additional token options.
Currently, ARIOCryptoOptions includes $dARIO and $tARIO, but you only display $ARIO in the dropdown. Consider validating or handling the other options more explicitly in case you expand support for them in the future.


185-225: Ensure comprehensive test coverage for balance logic.
You correctly handle the user’s choice between liquid, staked, or any combination. However, test coverage should confirm the correct displayed balance and selected funding source under different states (e.g., zero balance, partial balance, high balance).

src/components/Tooltips/ANTDetailsTip.tsx (1)

1-78: Component looks good overall, with well-defined functionality.

This tooltip component is well-structured and provides a clean way to display ANT details. The use of conditional rendering based on ID validity is a good approach, and the component is nicely modular.

The component demonstrates good practices by:

  1. Using TypeScript for type safety
  2. Providing default values for optional props
  3. Using proper validation before rendering ID components
  4. Creating a reusable UI element for displaying ANT metadata

Comment on lines +170 to +178
</div>
{selectedCrypto === formattedARIOTicker && (
<div className="flex flex-col gap-2 size-full items-start">
<span className="text-grey text-xs">
Select balance method:
</span>
<Tabs.Root
defaultValue={fundingSource}
value={fundingSource}
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

Avoid nested Tabs if possible.
You have nested Tabs for crypto balances. While it works, the nested approach can sometimes lead to confusion. Consider using a single set of components or disclaimers within the primary crypto tab (e.g., a single radio group for choosing between liquid/stakes).

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/components/pages/Register/Checkout.tsx (2)

69-74: Simplify handling of isInsufficientBalance.

There is an unnecessary ternary operator when checking for costDetail?.fundingPlan?.shortfall. Also, returning true for every non-crypto payment method effectively blocks those methods. Verify whether you intend to support 'card' or 'credits' in the future.

Consider the following patch to remove the redundant ternary operator:

- return costDetail?.fundingPlan?.shortfall ? true : false;
+ return !!costDetail?.fundingPlan?.shortfall;
🧰 Tools
🪛 Biome (1.9.4)

[error] 71-71: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


163-164: Address the wallet connectivity TODO.

The comment indicates the need to check wallet connectivity. This step is crucial to prevent errors in dispatching transactions.

Would you like me to propose a check to confirm wallet connectivity before proceeding?

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 814689d and 64e0f3e.

📒 Files selected for processing (1)
  • src/components/pages/Register/Checkout.tsx (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/components/pages/Register/Checkout.tsx (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
  • PaymentMethod (15-15)
🪛 Biome (1.9.4)
src/components/pages/Register/Checkout.tsx

[error] 71-71: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy-to-firebase
🔇 Additional comments (2)
src/components/pages/Register/Checkout.tsx (2)

112-115: Clarify handling of non-crypto payment methods.

Currently, the code sets the fees to 'Invalid payment method selected' into the returned object if the payment method is not 'crypto'. If you plan to integrate 'card' or 'credits' later (per the PaymentMethod type definition), prompt users or handle these methods appropriately.


190-273: Overall code quality is solid.

Other than the suggestions and questions above, the component effectively handles the checkout workflow, integrates well with your existing states/hooks, and includes appropriate error handling.

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 (9)
src/components/cards/DomainCheckoutCard.tsx (9)

9-12: Consider reordering and grouping imports.

The imports could be more organized to improve readability. Consider grouping them by type (external libraries, internal components, hooks, utilities) and using alphabetical ordering within each group.

import { useCountdown } from '@src/hooks/useCountdown';
import useDomainInfo from '@src/hooks/useDomainInfo';
import { useWalletState } from '@src/state';
import { isArweaveTransactionID } from '@src/utils';
import { DEFAULT_ANT_LOGO } from '@src/utils/constants';
import { RotateCw } from 'lucide-react';
import { ReactNode } from 'react';

-import ANTDetailsTip from '../Tooltips/ANTDetailsTip';
-import { Tooltip } from '../data-display';
-import { AntLogoIcon } from '../data-display/AntLogoIcon';
-import { ArNSLogo } from '../icons';
+// Internal components
+import { Tooltip } from '../data-display';
+import { AntLogoIcon } from '../data-display/AntLogoIcon';
+import ANTDetailsTip from '../Tooltips/ANTDetailsTip';
+import { ArNSLogo } from '../icons';

51-51: Consider adding descriptive alt text or aria-label for the AntLogoIcon.

For better accessibility, consider adding descriptive alt text or aria-label to the logo icon.

<AntLogoIcon
  id={
    isArweaveTransactionID(antId)
      ? domainInfo?.logo
      : DEFAULT_ANT_LOGO
  }
+ aria-label={`ANT logo for ${domain}`}
/>

54-73: Unnecessary whitespace and non-semantic span elements.

There are unnecessary whitespace string literals and non-semantic span elements that could be cleaned up for better code quality.

<div className="flex items-center w-fit ">
-  {' '}
  <span className="text-link-normal">ar://</span>
  <Tooltip
    tooltipOverrides={{
      overlayClassName: 'w-fit',
      overlayInnerStyle: {
        whiteSpace: 'nowrap',
        width: 'fit-content',
        padding: '0.625rem',
        border: '1px solid var(--text-faded)',
      },
    }}
    message={domain}
    icon={
      <span className="text-white max-w-[11.25rem] truncate">
-        {' '}
        {domain}
      </span>
    }
  />
-</div>{' '}
+</div>

82-82: Use consistent border styling with Tailwind classes.

Instead of using border-y-[1px], consider using Tailwind's built-in border classes for consistency.

<div
- className={`flex flex-col border-y-[1px] border-foreground gap-4 mt-8 py-6 size-full z-10`}
+ className={`flex flex-col border-y border-foreground gap-4 mt-8 py-6 size-full z-10`}
>

90-97: Add accessibility improvements to the order summary rows.

The current implementation lacks proper semantic structure for the data table. Consider using a more appropriate HTML structure or ARIA roles.

-{Object.entries(orderSummary).map(([key, value], i) => (
-  <div className="flex flex-row w-full text-sm" key={i}>
-    <span className="flex w-1/3 whitespace-nowrap text-grey">
-      {key}
-    </span>
-    <span className="flex w-1/2 whitespace-nowrap">{value}</span>
-  </div>
-))}
+<dl className="flex flex-col w-full gap-4 text-sm">
+  {Object.entries(orderSummary).map(([key, value], i) => (
+    <div className="flex flex-row w-full" key={i}>
+      <dt className="flex w-1/3 whitespace-nowrap text-grey">
+        {key}
+      </dt>
+      <dd className="flex w-1/2 whitespace-nowrap">{value}</dd>
+    </div>
+  ))}
+</dl>

100-100: Remove unnecessary whitespace character.

There's an unnecessary whitespace character inside a JSX expression.

-</div>{' '}
+</div>

103-115: Apply the same accessibility improvements to the fees section.

Similar to the order summary, the fees section would benefit from semantic HTML structure.

-{Object.entries(fees).map(([key, value], i) => (
-  <div
-    className="flex flex-row w-full text-sm justify-between"
-    key={i}
-  >
-    <span className="flex w-1/3 whitespace-nowrap text-grey">
-      {key}
-    </span>
-    <span className="flex w-1/2 whitespace-nowrap justify-end">
-      {value}
-    </span>
-  </div>
-))}
+<dl className="flex flex-col gap-2 w-full">
+  {Object.entries(fees).map(([key, value], i) => (
+    <div
+      className="flex flex-row w-full text-sm justify-between"
+      key={i}
+    >
+      <dt className="flex w-1/3 whitespace-nowrap text-grey">
+        {key}
+      </dt>
+      <dd className="flex w-1/2 whitespace-nowrap justify-end">
+        {value}
+      </dd>
+    </div>
+  ))}
+</dl>

134-144: Add appropriate ARIA attributes to the refresh button.

The refresh button would benefit from ARIA attributes for better accessibility, especially when showing the loading state.

<button
  onClick={refresh}
  className="flex gap-2 items-center justify-center text-center text-grey pointer"
+ aria-label="Refresh quote"
+ aria-busy={!countdownString}
>
  <RotateCw
    className={`text-grey size-4 ${
      !countdownString ? 'animate-spin' : ''
    }`}
+   aria-hidden="true"
  />
  Refresh
</button>

121-132: Improve the quote status display with semantic HTML and clearer status indicators.

The current implementation uses nested spans, which can be simplified with better semantic HTML and state handling.

-<span>
-  {quoteEndTimestamp < 0 ? (
-    <span className="text-error">Error fetching quote</span>
-  ) : countdownString ? (
-    <span className="whitespace-nowrap">
-      Quote updates in{' '}
-      <span className="text-white text-bold">{countdownString}</span>
-    </span>
-  ) : (
-    <span className="animate-pulse">Updating quote...</span>
-  )}
-</span>
+<div role="status">
+  {quoteEndTimestamp < 0 ? (
+    <span className="text-error" aria-live="polite">Error fetching quote</span>
+  ) : countdownString ? (
+    <span className="whitespace-nowrap">
+      Quote updates in{' '}
+      <strong className="text-white">{countdownString}</strong>
+    </span>
+  ) : (
+    <span className="animate-pulse" aria-live="polite">Updating quote...</span>
+  )}
+</div>
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 64e0f3e and ca39fd4.

📒 Files selected for processing (2)
  • src/components/Tooltips/ANTDetailsTip.tsx (1 hunks)
  • src/components/cards/DomainCheckoutCard.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Tooltips/ANTDetailsTip.tsx
🔇 Additional comments (5)
src/components/cards/DomainCheckoutCard.tsx (5)

43-43: Use Tailwind color variables instead of hex codes for better maintainability.

As mentioned in previous reviews, using hex codes directly makes maintenance harder. Define these colors in your Tailwind config and use the named colors.

-<div className="flex flex-col size-full bg-gradient-to-b from-[#1C1C1F] to-[#0E0E0F] rounded-t text-light-grey p-6">
+<div className="flex flex-col size-full bg-gradient-to-b from-dark-surface to-darker-surface rounded-t text-light-grey p-6">

61-62: Replace hard-coded pixel values with relative units.

As mentioned in previous reviews, use relative units like rem instead of px values for better responsiveness.

overlayInnerStyle: {
  whiteSpace: 'nowrap',
  width: 'fit-content',
- padding: '0.625rem',
- border: '1px solid var(--text-faded)',
+ padding: '0.625rem',
+ border: '1px solid var(--text-faded)',
},

76-76: Ensure proper optional chaining for nested properties.

As mentioned in a previous review, ensure proper optional chaining for all nested properties to prevent potential runtime errors.

<ANTDetailsTip
  antId={antId}
- targetId={domainInfo?.records?.['@']?.transactionId ?? targetId}
+ targetId={domainInfo?.records?.['@']?.transactionId ?? targetId}
  owner={domainInfo?.owner ?? walletAddress?.toString()}
/>

This looks like it's already been addressed in the current version, which is good!


1-39: LGTM! All imports, props definition, and state management look well-structured.

The component's imports, type definitions, and state management are well-structured. The use of custom hooks like useCountdown and useDomainInfo helps separate concerns and makes the component more readable.


119-146: Good error handling and loading state management in the quote timer.

The implementation properly handles different states of the quote timer, including error states, countdown, and loading states. The refresh button with loading animation is a nice touch for UX.

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 (3)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)

190-224: Reduce repetition by consolidating fund source triggers.

The three Tabs.Trigger elements for 'balance', 'any', and 'stakes' share similar structure. Consider generating them from a small data array to keep the code DRY and more easily extensible.

src/components/pages/Register/Checkout.tsx (2)

69-74: Simplify the conditional to remove the extraneous boolean literal.

Instead of using costDetail?.fundingPlan?.shortfall ? true : false;, consider:

- return costDetail?.fundingPlan?.shortfall ? true : false;
+ return !!costDetail?.fundingPlan?.shortfall;

This improves readability and follows the principle of avoiding unnecessary ternary expressions.

🧰 Tools
🪛 Biome (1.9.4)

[error] 71-71: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)


163-163: Address the wallet connection TODO.

The // TODO: check that it's connected comment indicates an incomplete verification step. Would you like me to open a new issue or implement a quick check for wallet connection here?

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ca39fd4 and caac677.

📒 Files selected for processing (3)
  • src/components/Tooltips/ANTDetailsTip.tsx (1 hunks)
  • src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1 hunks)
  • src/components/pages/Register/Checkout.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/Tooltips/ANTDetailsTip.tsx
🧰 Additional context used
🧬 Code Definitions (2)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
src/components/icons/index.ts (3)
  • ArIOTokenIcon (74-74)
  • TurboIcon (133-133)
  • CircleCheck (93-93)
src/components/pages/Register/Checkout.tsx (1)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (1)
  • PaymentMethod (15-15)
🪛 Biome (1.9.4)
src/components/pages/Register/Checkout.tsx

[error] 71-71: Unnecessary use of boolean literals in conditional expression.

Simplify your code by directly assigning the result without using a ternary operator.
If your goal is negation, you may use the logical NOT (!) or double NOT (!!) operator for clearer and concise code.
Check for more details about NOT operator.
Unsafe fix: Remove the conditional expression with

(lint/complexity/noUselessTernary)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: deploy-to-firebase
🔇 Additional comments (3)
src/components/forms/PaymentOptionsForm/PaymentOptionsForm.tsx (2)

15-17: Great job defining the PaymentMethod type.

Looks straightforward and should help maintain clear boundaries between payment options.


172-180: Nested Tabs approach was previously flagged.

This repeats the same nested Tabs pattern as noted in an earlier review comment. Reusing or refactoring to avoid deeply nested tab structures can improve clarity and maintainability.

src/components/pages/Register/Checkout.tsx (1)

217-235: Confirm the static “10 included” undernames.

The domain checkout card currently displays “Undernames: 10 included.” Verify whether this is always correct or should be dynamically fetched based on plan or tier. Let me know if you’d like an automated check.

@atticusofsparta atticusofsparta merged commit ef3615f into develop Apr 3, 2025
7 checks passed
@atticusofsparta atticusofsparta deleted the PE-7854-payments branch April 3, 2025 18:54
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.

3 participants