Show latest drop subscription status + balance#2231
Conversation
Signed-off-by: prxt6529 <prxt@6529.io>
📝 WalkthroughWalkthroughLatestDropNextMintSubscribe gained optional props ( Changes
Sequence Diagram(s)sequenceDiagram
participant NMD as NowMintingDetails
participant LDNMS as LatestDropNextMintSubscribe
participant API as Subscription API / useQuery
participant MSR as MemeSubscriptionRow
NMD->>LDNMS: Render (showOnlyWhenSubscribed=true, readonly=true)
LDNMS->>API: Query subscription status & details
API-->>LDNMS: { subscribed, balance, ... }
alt subscribed === false
LDNMS-->>NMD: Return null (no render)
else subscribed === true
LDNMS->>LDNMS: Compute balanceLabel (finite → Intl.NumberFormat)
LDNMS->>MSR: Render with balanceLabel, subscribedView=true, readonly=true
MSR-->>LDNMS: Render compact subscribed UI (header, count ratio, balance)
LDNMS-->>NMD: Subscription section displayed
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
components/home/now-minting/LatestDropNextMintSubscribe.tsx (1)
85-90: Consider handling non-finite balance values.The
balancefield is typed asnumber, which could potentially beNaNorInfinityin edge cases (e.g., API errors, corrupt data). The current fallback?? 0only handlesundefined/null, butIntl.NumberFormatwill renderNaNas "NaN" andInfinityas "∞", which could be confusing to users.🛡️ Defensive fix for non-finite values
const balanceLabel = useMemo(() => { - const balance = details?.balance ?? 0; + const rawBalance = details?.balance ?? 0; + const balance = Number.isFinite(rawBalance) ? rawBalance : 0; return new Intl.NumberFormat(undefined, { maximumFractionDigits: 6, }).format(Math.round(balance * 1_000_000) / 1_000_000); }, [details?.balance]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/home/now-minting/LatestDropNextMintSubscribe.tsx` around lines 85 - 90, The computed balanceLabel should guard against non-finite numbers: inside the useMemo for balanceLabel (which reads details?.balance), validate the numeric value with Number.isFinite (or isFinite) and fallback to 0 when the value is NaN or Infinity before rounding/formatting; then pass that safe finite number into the existing Math.round(...)/Intl.NumberFormat logic so Intl.NumberFormat never receives NaN/Infinity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@components/home/now-minting/LatestDropNextMintSubscribe.tsx`:
- Around line 85-90: The computed balanceLabel should guard against non-finite
numbers: inside the useMemo for balanceLabel (which reads details?.balance),
validate the numeric value with Number.isFinite (or isFinite) and fallback to 0
when the value is NaN or Infinity before rounding/formatting; then pass that
safe finite number into the existing Math.round(...)/Intl.NumberFormat logic so
Intl.NumberFormat never receives NaN/Infinity.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 870b1b61-478b-48e7-bac9-180ea4a8f504
📒 Files selected for processing (5)
__tests__/components/home/LatestDropNextMintSubscribe.test.tsx__tests__/components/home/NowMintingDetails.test.tsxcomponents/home/now-minting/LatestDropNextMintSubscribe.tsxcomponents/home/now-minting/NowMintingDetails.tsxcomponents/user/subscriptions/MemeSubscriptionRow.tsx
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
app/page.tsx (2)
107-117: Consider configuring QueryClient defaults for SSR.Creating a bare
QueryClient()in a server component means every request gets a fresh client (correct), but the defaultstaleTimeis0. If the prefetched data is immediately considered stale on the client, React Query may refetch on mount, negating the SSR benefit.💡 Suggested improvement
export default async function Page() { - const queryClient = new QueryClient(); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + staleTime: 60 * 1000, // 1 minute - adjust as needed + }, + }, + }); await prefetchHomeSubscriptionState(queryClient);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/page.tsx` around lines 107 - 117, The QueryClient created in Page() uses default staleTime=0 causing prefetched data to be immediately stale and trigger refetch on mount; update the QueryClient instantiation in Page (where QueryClient is constructed before prefetchHomeSubscriptionState/dehydrate/HydrationBoundary) to pass sensible defaultOptions (e.g., set queries.staleTime to a nonzero value and/or cacheTime) so SSR-prefetched queries remain fresh on the client and avoid unnecessary refetches.
35-45: JWT decoding silently catches all errors—consider logging for observability.While returning
nullon decode failure is safe, silently swallowing errors makes debugging authentication issues harder in production. Consider logging the error at a debug/warn level.💡 Optional improvement
try { return jwtDecode<WalletJwtPayload>(jwt).sub?.toLowerCase() ?? null; } catch { + // Optionally log for observability: console.warn('Failed to decode wallet JWT'); return null; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/page.tsx` around lines 35 - 45, The getWalletAddressFromJwt function currently swallows all thrown errors from jwtDecode; update its catch block to capture the caught error (e.g., "err") and log it at an appropriate level (debug or warn) before returning null so decoding failures are observable; reference the function getWalletAddressFromJwt, the jwtDecode call, and the WalletJwtPayload type when making the change and use the project's logger (or console as fallback) to record the error and a brief context message.__tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsx (1)
20-81: Consider adding edge case tests for robustness.The current test covers the happy path well. Consider adding tests for:
subscribedViewwithbalanceLabelto verify the balance UI renderssubscribedViewwhenfinalWithMetadatais null (no phase info displayed)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@__tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsx` around lines 20 - 81, Add two edge-case tests in MemeSubscriptionRow.test.tsx: (1) a test that renders <MemeSubscriptionRow ... subscribedView balanceLabel="0.5" .../> and asserts the balance UI renders (e.g., text containing the balanceLabel) while keeping other props similar to the existing happy-path test; (2) a test that simulates no final metadata by making useQueryMock return { data: null } for the "consolidation-final-subscription" queryKey and rendering <MemeSubscriptionRow subscribedView .../> then asserting that the phase line (the text matched by /Phase:/ or the element rendered by MemeSubscriptionRow when finalWithMetadata exists) is not present; locate usage of useQueryMock in beforeEach and the component props token_id/contract/subscribed/subscribed_count, subscribedView, balanceLabel and finalWithMetadata to implement these assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@__tests__/components/home/LatestDropNextMintSubscribe.test.tsx`:
- Around line 94-96: The test currently only checks for the prefix with
expect(screen.getByTestId("meme-subscription-row")).toHaveTextContent(/balance:/)
— update this to assert the exact rendered fallback value given the default mock
(details.balance is undefined). Inspect the mock that supplies details.balance
and change the assertion on getByTestId("meme-subscription-row") to match the
actual expected output (for example toHaveTextContent(/balance:\s*0/),
toHaveTextContent(/balance:\s*N\/A/), or toHaveTextContent(/balance:\s*$/)
depending on the component's fallback behavior) so the test verifies the full
balance string rather than just the prefix.
In `@components/user/subscriptions/MemeSubscriptionRow.tsx`:
- Around line 289-292: The read-only view shows subscribedCount derived from
props.subscription.subscribed_count using nullish coalescing which doesn't treat
explicit 0 as a fallback; update the calculation in MemeSubscriptionRow (where
subscribedCount is computed) to treat 0 like null/undefined (e.g., use a falsy
check or explicit === 0 handling so subscribedCount becomes 1 when
props.subscription.subscribed_count is 0/undefined/null), and leave
LatestDropNextMintSubscribe as-is since it already uses ?? 1; ensure
UserPageSubscriptionsUpcoming-supplied subscriptions are normalized similarly or
handled in the same subscribedCount logic.
---
Nitpick comments:
In `@__tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsx`:
- Around line 20-81: Add two edge-case tests in MemeSubscriptionRow.test.tsx:
(1) a test that renders <MemeSubscriptionRow ... subscribedView
balanceLabel="0.5" .../> and asserts the balance UI renders (e.g., text
containing the balanceLabel) while keeping other props similar to the existing
happy-path test; (2) a test that simulates no final metadata by making
useQueryMock return { data: null } for the "consolidation-final-subscription"
queryKey and rendering <MemeSubscriptionRow subscribedView .../> then asserting
that the phase line (the text matched by /Phase:/ or the element rendered by
MemeSubscriptionRow when finalWithMetadata exists) is not present; locate usage
of useQueryMock in beforeEach and the component props
token_id/contract/subscribed/subscribed_count, subscribedView, balanceLabel and
finalWithMetadata to implement these assertions.
In `@app/page.tsx`:
- Around line 107-117: The QueryClient created in Page() uses default
staleTime=0 causing prefetched data to be immediately stale and trigger refetch
on mount; update the QueryClient instantiation in Page (where QueryClient is
constructed before prefetchHomeSubscriptionState/dehydrate/HydrationBoundary) to
pass sensible defaultOptions (e.g., set queries.staleTime to a nonzero value
and/or cacheTime) so SSR-prefetched queries remain fresh on the client and avoid
unnecessary refetches.
- Around line 35-45: The getWalletAddressFromJwt function currently swallows all
thrown errors from jwtDecode; update its catch block to capture the caught error
(e.g., "err") and log it at an appropriate level (debug or warn) before
returning null so decoding failures are observable; reference the function
getWalletAddressFromJwt, the jwtDecode call, and the WalletJwtPayload type when
making the change and use the project's logger (or console as fallback) to
record the error and a brief context message.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: aa758cd8-6ad5-44bf-86f3-f83c5b8f0a7e
📒 Files selected for processing (5)
__tests__/components/home/LatestDropNextMintSubscribe.test.tsx__tests__/components/user/subscriptions/MemeSubscriptionRow.test.tsxapp/page.tsxcomponents/home/now-minting/LatestDropNextMintSubscribe.tsxcomponents/user/subscriptions/MemeSubscriptionRow.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- components/home/now-minting/LatestDropNextMintSubscribe.tsx
There was a problem hiding this comment.
🧹 Nitpick comments (1)
components/user/subscriptions/MemeSubscriptionRow.tsx (1)
277-287: Balance label lacks accessibility context.The balance label displays a value with an
EthereumIconbut screen readers won't understand that the icon represents Ethereum/ETH currency. Consider adding anaria-labelor visually hidden text for accessibility.♿ Proposed accessibility improvement
{props.balanceLabel && ( <span className="tw-flex tw-items-center tw-gap-1 tw-text-sm tw-leading-none tw-text-iron-400"> <span className="tw-leading-none">Balance</span> <span className="tw-leading-none tw-text-iron-300"> {props.balanceLabel} </span> - <span className="tw-flex tw-size-3.5 tw-items-center tw-justify-center tw-self-center tw-text-iron-400"> + <span + className="tw-flex tw-size-3.5 tw-items-center tw-justify-center tw-self-center tw-text-iron-400" + aria-label="ETH" + role="img" + > <EthereumIcon /> </span> </span> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/user/subscriptions/MemeSubscriptionRow.tsx` around lines 277 - 287, The balance label (props.balanceLabel) renders an EthereumIcon with no accessible text, so screen readers can't identify the currency; update the MemeSubscriptionRow rendering to provide accessibility by either adding an aria-label (e.g., aria-label="Ethereum" or aria-hidden="true" on the decorative part plus a visually hidden text node saying "ETH") to the EthereumIcon span, or include a visually-hidden span (screen-reader-only) adjacent to the icon that reads "Ethereum" or "ETH" so assistive tech correctly announces the currency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@components/user/subscriptions/MemeSubscriptionRow.tsx`:
- Around line 277-287: The balance label (props.balanceLabel) renders an
EthereumIcon with no accessible text, so screen readers can't identify the
currency; update the MemeSubscriptionRow rendering to provide accessibility by
either adding an aria-label (e.g., aria-label="Ethereum" or aria-hidden="true"
on the decorative part plus a visually hidden text node saying "ETH") to the
EthereumIcon span, or include a visually-hidden span (screen-reader-only)
adjacent to the icon that reads "Ethereum" or "ETH" so assistive tech correctly
announces the currency.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: fcc6d690-321d-473a-95ff-7afb0942ff2a
📒 Files selected for processing (1)
components/user/subscriptions/MemeSubscriptionRow.tsx
Signed-off-by: prxt6529 <prxt@6529.io>
|



Summary by CodeRabbit
New Features
Tests