feat: chainflip lending dashboard revamp#12189
feat: chainflip lending dashboard revamp#12189gomesalexandre wants to merge 19 commits intodevelopfrom
Conversation
- Replace MyBalances with new Dashboard component with tabs (My Dashboard / Markets) - Add per-section cards: Free Balance, Supplied, Collateral, Borrowed with contextual CTAs - Add DashboardSidebar with Borrowing Power gauge and Next Steps card with decorative art - Add InitView for first-time users with Get Started hero, Lending Markets table, info cards - Add LoanHealth card with horizontal multi-segment LTV bar (Safe/Risky/Liquidation zones) - Revamp all confirm screens (Deposit, Supply, Withdraw, Borrow, Repay, Collateral, Egress) to use centered asset icon + amount, info rows, side-by-side Back/Confirm buttons - Add Pool APY and Current Position stats to Supply input screen - Add Borrow APR column to Markets table, reorder columns to match Figma - Add Lending Markets section title with description - Fix double button issue in empty state sections - Use outline button style with + prefix for CTAs per Figma - Add Asset/Balance column headers to Free Balance section - Update header to show user-specific summary cards when wallet connected - Add ~50 new translation keys Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite AssetConstellation with larger icons (52-88px), organic positions, no network badges (showNetworkIcon=false), subtle orbital arcs - Rewrite InfoCard with concentric ring art on right side, proper accent colors, radial lines for borrow card - Add Borrow APR column to Markets table (6 columns matching Figma) - Reorder Markets columns: Asset, Supply APY, Total Supplied, Borrow APR, Total Borrowed, Utilisation - Add Lending Markets section title with description - Fix hero card: inline Deposit button + FLIP note, more padding, borderRadius 2xl - Fix Supplied empty state CTA from "+ Supply" to "+ Deposit" per Figma Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Download and embed orbital ring SVGs from Figma MCP for hero constellation - Download and embed concentric ring SVGs for Earn Yield and Borrow info cards - Use sparkles-icon.svg and refresh-icon.svg from Figma for info card centers - Remove showNetworkIcon from hero asset icons (plain icons like Figma) - Match Figma card styling: rgba bg/border, 2xl border radius, 32px/64px padding - Inline "Requires 2 FLIP" note next to Deposit button per Figma layout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Pool APY stat row at top was showing alongside a duplicate APY info row below the divider. Kept the top stat row (matches Figma) and removed the bottom duplicate. Estimated yearly earnings still shows when user enters an amount. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace CSS-based concentric rings with exact Figma SVG assets for both green (supply) and purple (borrow) variants. Remove unused Icon, TbRefresh, TbSparkles imports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All Next Steps card buttons now use height=40px, borderRadius=xl, fontWeight=semibold matching the Figma design. The Add Collateral button uses subtle whiteAlpha.50 bg for the outline variant. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nfirm, init markets - SectionHeader primary action buttons now filled blue (matching Figma) - Supplied section column header "Amount" → "Supplied" - Collateral section now has Asset/Amount column headers when populated - Supply confirm wraps amount in bordered card per Figma - Supply confirm adds Asset info row + parameterized destination label - InitView MarketsTable now shows 6 columns including Borrow APR - InitView MarketsTable adds description text matching Markets.tsx Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Updated steps to test no-wallet, init view, funded dashboard, empty sections - Updated modal steps to open from dashboard sections (not pool page tabs) - Added Markets tab verification step - Removed outdated pool page navigation steps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR introduces a comprehensive redesign of the Chainflip Lending dashboard and confirmation flow interfaces. Key updates include new dashboard components (Dashboard, InitView, DashboardSections, DashboardSidebar, LoanHealth) to display user balances and positions, restructured confirmation modals with two-button footers and back navigation, an enhanced LTV Gauge with multi-segment visuals, and expanded translation keys for lending-related UI labels. The Markets page now features tab-based navigation for dashboard and markets views, while Supply inputs gain APY and position tracking details. Changes
Sequence DiagramsequenceDiagram
participant User
participant Dashboard as Dashboard Component
participant Sections as DashboardSections
participant Sidebar as DashboardSidebar
participant Hooks as Data Hooks
participant Modal as Modal System
User->>Dashboard: Load /chainflip-lending
Dashboard->>Hooks: useChainflipAccount, useChainflipFreeBalances,<br/>useChainflipSupplyPositions, useChainflipLoanAccount
Hooks-->>Dashboard: hasFreeBalance, hasAnyPosition, funded status
alt User has no positions/funding
Dashboard->>Dashboard: showInitView = true
Dashboard->>User: Render InitView with markets table
User->>User: Browse available markets
else User is funded with positions
Dashboard->>Dashboard: showInitView = false
Dashboard->>Sections: Render 4 sections
Sections->>Hooks: Fetch balances & positions
Hooks-->>Sections: Asset data with amounts, APYs, rates
Sections-->>Dashboard: FreeBalance, Supplied, Collateral, Borrowed rows
Dashboard->>Sidebar: Render sidebar components
Sidebar->>Hooks: useChainflipLoanAccount, useChainflipLtvThresholds
Hooks-->>Sidebar: LTV, collateral, borrowed values
Sidebar-->>Dashboard: BorrowingPowerCard, NextStepsCard
Dashboard-->>User: Full dashboard layout
end
User->>Sections: Click "Deposit" or "Supply" or "Borrow"
Sections->>Modal: Open chainflipLending modal
Modal-->>User: Display confirmation flow
User->>Modal: Confirm action
Modal->>Modal: Show success with "View Dashboard" button
User->>Modal: Click "View Dashboard"
Modal->>Dashboard: Navigate to /chainflip-lending
Dashboard-->>User: Refresh and display updated data
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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.
Actionable comments posted: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/pages/ChainflipLending/Pool/components/Withdraw/WithdrawConfirm.tsx (1)
68-79:⚠️ Potential issue | 🟠 MajorRefresh the lending queries before
View Dashboard.
handleDone()invalidates the free-balance/account queries before closing, but the new dashboard CTA skips that step. After a successful withdraw, this can route the user to a dashboard that still shows the pre-withdraw values until the cached queries expire.Suggested fix
+ const invalidateWithdrawQueries = useCallback(async () => { + if (scAccount) { + await queryClient.invalidateQueries(reactQueries.chainflipLending.freeBalances(scAccount)) + await queryClient.invalidateQueries(reactQueries.chainflipLending.accountInfo(scAccount)) + } + }, [scAccount, queryClient]) + const handleDone = useCallback(async () => { - if (scAccount) { - await queryClient.invalidateQueries(reactQueries.chainflipLending.freeBalances(scAccount)) - await queryClient.invalidateQueries(reactQueries.chainflipLending.accountInfo(scAccount)) - } + await invalidateWithdrawQueries() closeModal() - }, [scAccount, queryClient, closeModal]) + }, [invalidateWithdrawQueries, closeModal]) - const handleViewDashboard = useCallback(() => { + const handleViewDashboard = useCallback(async () => { + await invalidateWithdrawQueries() closeModal() navigate('/chainflip-lending') - }, [closeModal, navigate]) + }, [invalidateWithdrawQueries, closeModal, navigate])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/Pool/components/Withdraw/WithdrawConfirm.tsx` around lines 68 - 79, The View Dashboard CTA bypasses the cache refresh done in handleDone, so update handleViewDashboard to refresh the same lending queries before closing/navigating: if scAccount is present, call queryClient.invalidateQueries(reactQueries.chainflipLending.freeBalances(scAccount)) and queryClient.invalidateQueries(reactQueries.chainflipLending.accountInfo(scAccount)) (or simply call handleDone() to reuse logic), then closeModal() and navigate('/chainflip-lending'); ensure you reference scAccount, queryClient, reactQueries.chainflipLending.freeBalances, reactQueries.chainflipLending.accountInfo, closeModal, navigate, and handleDone in the change.src/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsx (1)
188-195:⚠️ Potential issue | 🟡 MinorUse
.toFixed()instead of.toString()to avoid scientific notation in the fiat Max path.The current code can produce scientific notation for small balances when converting BigNumber to string for
setInputValue(). This breaks display inNumericFormat.Suggested fix
const handleMaxClick = useCallback(() => { if (isFiat && marketData?.price) { - const fiatMax = bnOrZero(availableCryptoPrecision).times(marketData.price).toString() + const fiatMax = bnOrZero(availableCryptoPrecision) + .times(marketData.price) + .decimalPlaces(2, 1) + .toFixed() setInputValue(fiatMax) } else { setInputValue(availableCryptoPrecision) } }, [availableCryptoPrecision, isFiat, marketData?.price])Additionally, replace the hardcoded
suffix=' / year'at line 412 with the translation key:suffix={translate('chainflipLending.dashboard.yearlyEarningsSuffix').replace('%{amount} ', '')}or extract the suffix portion differently, since the translation key"yearlyEarningsSuffix": "%{amount} / year"is already defined but not being used.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsx` around lines 188 - 195, The handleMaxClick handler can produce scientific notation because it calls .toString() on the BigNumber calculation; change the fiat branch to use .toFixed() (e.g., bnOrZero(availableCryptoPrecision).times(marketData.price).toFixed()) before calling setInputValue to ensure a non-scientific numeric string for NumericFormat; update the dependency names handleMaxClick, availableCryptoPrecision, marketData.price, and setInputValue when locating the code. Also replace the hardcoded suffix=' / year' with the translated suffix by using the translation key chainflipLending.dashboard.yearlyEarningsSuffix and extracting/removing the %{amount} placeholder (for example: translate('chainflipLending.dashboard.yearlyEarningsSuffix').replace('%{amount} ', '')) where the suffix is set.
🧹 Nitpick comments (3)
e2e/fixtures/chainflip-lending-revamp-ui.yaml (1)
44-75: Cover at least one confirm/success path in this fixture.These steps stop at opening the revamped modals, but the PR also changes the confirm/success footers (
Back,Close,View Dashboard). Adding one happy-path flow that reaches success and asserts the dashboard redirect would keep the new navigation path under test.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@e2e/fixtures/chainflip-lending-revamp-ui.yaml` around lines 44 - 75, The fixture stops at opening modals and doesn't exercise the confirm/success path; add a happy-path scenario that fills a valid amount, clicks the modal's blue "Next" then "Confirm"/"Supply"/"Add Collateral" action to trigger the success footer, assert the presence of the success footer buttons ("Back", "Close", "View Dashboard"), click "View Dashboard" (or verify the dashboard redirect/navigation), and assert the dashboard is shown (e.g., Free Balance or Dashboard heading) to cover the new navigation path introduced by the PR.src/pages/ChainflipLending/components/DashboardSections.tsx (2)
262-269: DuplicatepoolsByAssetIdcomputation in SuppliedSection and BorrowedSection.Both sections compute the same
poolsByAssetIdlookup map. Consider extracting this to a shared hook or computing it once in a parent component if both sections are rendered together. However, given the PR's UI-focused scope, this can be deferred.Also applies to: 485-492
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSections.tsx` around lines 262 - 269, The poolsByAssetId lookup is computed twice (in SuppliedSection and BorrowedSection) using the same reduce logic; extract this into a single shared implementation by creating a hook (e.g., usePoolsByAssetId) or computing it once in the parent component that renders both sections and passing it down as a prop; update both SuppliedSection and BorrowedSection to consume the shared usePoolsByAssetId or the passed-in poolsByAssetId instead of duplicating the reduce, keeping the existing shape (Partial<Record<AssetId, ChainflipLendingPoolWithFiat>>) and relying on the same dependency (pools).
207-208: Hardcoded column header strings should use translation keys.Column headers like "Asset", "Balance", "Amount", and "Supplied" are hardcoded in English. For consistency with the rest of the file (which uses
translate()andText translation=props), these should use translation keys to support i18n.Example fix for FreeBalanceSection headers (Line 207-208)
<Flex justifyContent='space-between' px={0} py={1} color='text.subtle' fontSize='xs' fontWeight='bold' > - <RawText>Asset</RawText> - <RawText>Balance</RawText> + <Text translation='chainflipLending.dashboard.asset' /> + <Text translation='chainflipLending.dashboard.balance' /> </Flex>Also applies to: 326-326, 329-329, 434-435, 570-570, 573-573
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSections.tsx` around lines 207 - 208, Replace hardcoded column header strings in DashboardSections.tsx (e.g., the RawText "Asset", "Balance", "Amount", "Supplied" used in FreeBalanceSection and other sections) with i18n translation calls to match the file's convention—use the translate('your.translation.key') helper or the <Text translation="..."> prop depending on surrounding code; update each RawText or header node (refer to FreeBalanceSection and other header occurrences around the areas noted: ~lines 207-208, 326, 329, 434-435, 570, 573) to call the appropriate translation key (create meaningful keys like dashboard.asset, dashboard.balance, dashboard.amount, dashboard.supplied) so strings are not hardcoded.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/pages/ChainflipLending/components/Dashboard.tsx`:
- Around line 20-46: The init view is showing prematurely because showInitView
relies on isFunded/isLpRegistered and empty arrays while the hooks are still
loading; update the logic to wait for the hooks to finish before deciding: read
and use the loading/initialized flags returned by useChainflipAccount,
useChainflipFreeBalances, useChainflipSupplyPositions and
useChainflipLoanAccount (or add them if missing) and only compute showInitView
after those loaders are settled; reference isFunded, isLpRegistered,
freeBalances, supplyPositions, collateralWithFiat, loansWithFiat and compute
showInitView to return false while any of those hooks are loading so InitView is
not rendered until all data has resolved.
In `@src/pages/ChainflipLending/components/InitView.tsx`:
- Around line 282-284: The HelperTooltip wrapping the "Lending Markets" Heading
is using the wrong translation key
(translate('chainflipLending.utilisationTooltip')), which is intended for the
utilisation column; update the tooltip to a markets-appropriate key by replacing
utilisationTooltip with a markets-specific key (e.g.
'chainflipLending.lendingMarketsTooltip' or 'chainflipLending.marketsTooltip')
or add a new translation key and use it in the HelperTooltip that wraps the
Heading component so the tooltip context matches the "Lending Markets" heading.
In `@src/pages/ChainflipLending/components/Markets.tsx`:
- Around line 153-159: The HelperTooltip wrapped around the heading uses the
wrong translation key (translate('chainflipLending.utilisationTooltip')); update
the tooltip to either remove the HelperTooltip entirely or point it at a
title-specific key such as 'chainflipLending.lendingMarketsTooltip' (or the
correct existing title tooltip key), by editing the HelperTooltip's label prop
where HelperTooltip is used around the Text component in Markets.tsx so it
reflects the lending markets title instead of the utilisation tooltip.
In `@src/pages/ChainflipLending/Pool/components/Borrow/BorrowConfirm.tsx`:
- Around line 94-97: The view-dashboard handler currently closes the modal and
navigates directly, causing stale loan data; modify handleViewDashboard to run
the same completion path used in handleDone before navigating (either call
handleDone() from handleViewDashboard or extract the invalidation/refresh logic
from handleDone into a shared function and invoke it), then call closeModal()
and navigate('/chainflip-lending') after that refresh completes; reference the
existing functions handleViewDashboard, handleDone, closeModal, and navigate to
locate and reuse the completion/invalidation logic.
In `@src/pages/ChainflipLending/Pool/components/Borrow/LtvGauge.tsx`:
- Around line 95-111: Guard against division-by-zero when computing the inner
Flex width: detect when currentLtv or thumbPosition is 0 (or <= 0) and avoid
calculating (100 / thumbPosition) * 100; instead set the Flex width to a safe
value (e.g. '0%') in that case. Update the code that sets the Flex width
expression (the element using ${(100 / thumbPosition) * 100}% ) to compute a
conditional innerWidth = thumbPosition > 0 ? `${(100 / thumbPosition) * 100}%` :
'0%' so safeWidth, riskyWidth and liquidationWidth render without producing
"Infinity%". Ensure you reference thumbPosition/currentLtv and the Flex
containing safeWidth/riskyWidth/liquidationWidth when making the change.
In `@src/pages/ChainflipLending/Pool/components/Borrow/RepayConfirm.tsx`:
- Around line 322-325: The Badge text is hardcoded as "Full" in RepayConfirm
when isFullRepayment is true; replace that literal with a localized string (use
the component's i18n function, e.g., t('repay.full') or the existing translation
hook used in this component) or accept a translated label via props, so the
Badge (Badge component shown when isFullRepayment) displays a locale-aware label
(or remove the extra text entirely if you prefer only the visual badge).
- Around line 87-90: handleViewDashboard currently closes the modal and
navigates directly, which skips the state invalidation done by handleDone and
can leave the dashboard with stale repay data; update handleViewDashboard to
perform the same completion path as handleDone (i.e., run the state invalidation
/ refresh logic or simply call/await handleDone()) before calling closeModal()
and navigate('/chainflip-lending'), ensuring you preserve the dependency array
([closeModal, navigate]) and that any async operations are awaited so navigation
only occurs after the lending state refresh completes.
In `@src/pages/ChainflipLending/Pool/components/Deposit/DepositConfirm.tsx`:
- Around line 172-175: handleViewDashboard currently just closes the modal and
navigates away, causing stale balances; change it to run the same
completion/cleanup logic used by handleDone before navigating. Specifically,
invoke the same function or shared completion helper that handleDone uses (or
call handleDone directly) to run invalidation, state refresh and any cleanup,
then after that resolution call closeModal() and navigate('/chainflip-lending');
ensure dependencies include whatever helper or handleDone is referenced so the
callback is stable.
In `@src/pages/ChainflipLending/Pool/components/Egress/EgressConfirm.tsx`:
- Around line 85-88: handleViewDashboard currently closes the modal and
navigates away without running the same completion/invalidation steps in
handleDone, which can leave balances stale; update handleViewDashboard to
perform the same completion path as handleDone (either call handleDone()
directly or extract and invoke the shared completion/invalidation function used
by handleDone) before calling closeModal() and navigate('/chainflip-lending'),
ensuring the same invalidate/cache refresh logic runs; reference
handleViewDashboard, handleDone, closeModal, and navigate to locate and reuse
the completion logic.
In `@src/pages/ChainflipLending/Pool/components/Supply/SupplyConfirm.tsx`:
- Around line 86-89: handleViewDashboard currently closes the modal and
navigates directly, skipping the completion/cleanup logic in handleDone and
leaving supply/account caches stale; update handleViewDashboard to perform the
same completion path as handleDone before navigating — either call handleDone()
(or extract the invalidate/cleanup steps from handleDone into a shared helper
like completeSupplyFlow() and invoke that from both handleDone and
handleViewDashboard) and only after that finishes call closeModal() and
navigate('/chainflip-lending').
In `@src/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsx`:
- Around line 403-413: Replace the hardcoded suffix string in the Amount.Fiat
component with the localized translation key; specifically, in SupplyInput.tsx
where estYearlyEarningsFiat is rendered with Amount.Fiat, call
translate('chainflipLending.supply.yearlyEarningsSuffix') (or store it in a
variable) and pass that result as the suffix prop to Amount.Fiat so the suffix
is localized for all locales.
---
Outside diff comments:
In `@src/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsx`:
- Around line 188-195: The handleMaxClick handler can produce scientific
notation because it calls .toString() on the BigNumber calculation; change the
fiat branch to use .toFixed() (e.g.,
bnOrZero(availableCryptoPrecision).times(marketData.price).toFixed()) before
calling setInputValue to ensure a non-scientific numeric string for
NumericFormat; update the dependency names handleMaxClick,
availableCryptoPrecision, marketData.price, and setInputValue when locating the
code. Also replace the hardcoded suffix=' / year' with the translated suffix by
using the translation key chainflipLending.dashboard.yearlyEarningsSuffix and
extracting/removing the %{amount} placeholder (for example:
translate('chainflipLending.dashboard.yearlyEarningsSuffix').replace('%{amount}
', '')) where the suffix is set.
In `@src/pages/ChainflipLending/Pool/components/Withdraw/WithdrawConfirm.tsx`:
- Around line 68-79: The View Dashboard CTA bypasses the cache refresh done in
handleDone, so update handleViewDashboard to refresh the same lending queries
before closing/navigating: if scAccount is present, call
queryClient.invalidateQueries(reactQueries.chainflipLending.freeBalances(scAccount))
and
queryClient.invalidateQueries(reactQueries.chainflipLending.accountInfo(scAccount))
(or simply call handleDone() to reuse logic), then closeModal() and
navigate('/chainflip-lending'); ensure you reference scAccount, queryClient,
reactQueries.chainflipLending.freeBalances,
reactQueries.chainflipLending.accountInfo, closeModal, navigate, and handleDone
in the change.
---
Nitpick comments:
In `@e2e/fixtures/chainflip-lending-revamp-ui.yaml`:
- Around line 44-75: The fixture stops at opening modals and doesn't exercise
the confirm/success path; add a happy-path scenario that fills a valid amount,
clicks the modal's blue "Next" then "Confirm"/"Supply"/"Add Collateral" action
to trigger the success footer, assert the presence of the success footer buttons
("Back", "Close", "View Dashboard"), click "View Dashboard" (or verify the
dashboard redirect/navigation), and assert the dashboard is shown (e.g., Free
Balance or Dashboard heading) to cover the new navigation path introduced by the
PR.
In `@src/pages/ChainflipLending/components/DashboardSections.tsx`:
- Around line 262-269: The poolsByAssetId lookup is computed twice (in
SuppliedSection and BorrowedSection) using the same reduce logic; extract this
into a single shared implementation by creating a hook (e.g., usePoolsByAssetId)
or computing it once in the parent component that renders both sections and
passing it down as a prop; update both SuppliedSection and BorrowedSection to
consume the shared usePoolsByAssetId or the passed-in poolsByAssetId instead of
duplicating the reduce, keeping the existing shape (Partial<Record<AssetId,
ChainflipLendingPoolWithFiat>>) and relying on the same dependency (pools).
- Around line 207-208: Replace hardcoded column header strings in
DashboardSections.tsx (e.g., the RawText "Asset", "Balance", "Amount",
"Supplied" used in FreeBalanceSection and other sections) with i18n translation
calls to match the file's convention—use the translate('your.translation.key')
helper or the <Text translation="..."> prop depending on surrounding code;
update each RawText or header node (refer to FreeBalanceSection and other header
occurrences around the areas noted: ~lines 207-208, 326, 329, 434-435, 570, 573)
to call the appropriate translation key (create meaningful keys like
dashboard.asset, dashboard.balance, dashboard.amount, dashboard.supplied) so
strings are not hardcoded.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ec642382-e1cf-4028-815d-17f934aaf768
⛔ Files ignored due to path filters (18)
src/assets/chainflip-lending/borrow-glow.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/borrow-ring-1.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/borrow-ring-2.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/borrow-ring-3.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/borrow-ring-inner.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/earn-glow.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/earn-ring-inner.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/earn-ring-middle.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/earn-ring-outer.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/glow-btc.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/glow-eth.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/orbital-btc.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/orbital-eth.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/orbital-sol.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/orbital-tether.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/orbital-usdc.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/refresh-icon.svgis excluded by!**/*.svgsrc/assets/chainflip-lending/sparkles-icon.svgis excluded by!**/*.svg
📒 Files selected for processing (19)
e2e/fixtures/chainflip-lending-revamp-ui.yamlsrc/assets/translations/en/main.jsonsrc/pages/ChainflipLending/Pool/components/Borrow/BorrowConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/CollateralConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/LtvGauge.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/RepayConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Deposit/DepositConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Egress/EgressConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Supply/SupplyConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsxsrc/pages/ChainflipLending/Pool/components/Withdraw/WithdrawConfirm.tsxsrc/pages/ChainflipLending/components/ChainflipLendingHeader.tsxsrc/pages/ChainflipLending/components/Dashboard.tsxsrc/pages/ChainflipLending/components/DashboardSections.tsxsrc/pages/ChainflipLending/components/DashboardSidebar.tsxsrc/pages/ChainflipLending/components/InitView.tsxsrc/pages/ChainflipLending/components/LoanHealth.tsxsrc/pages/ChainflipLending/components/Markets.tsxsrc/pages/ChainflipLending/components/MyBalances.tsx
💤 Files with no reviewable changes (1)
- src/pages/ChainflipLending/components/MyBalances.tsx
src/pages/ChainflipLending/Pool/components/Borrow/BorrowConfirm.tsx
Outdated
Show resolved
Hide resolved
src/pages/ChainflipLending/Pool/components/Deposit/DepositConfirm.tsx
Outdated
Show resolved
Hide resolved
src/pages/ChainflipLending/Pool/components/Egress/EgressConfirm.tsx
Outdated
Show resolved
Hide resolved
src/pages/ChainflipLending/Pool/components/Supply/SupplyConfirm.tsx
Outdated
Show resolved
Hide resolved
- handleViewDashboard now calls handleDone() for cache invalidation before navigating (BorrowConfirm, RepayConfirm, DepositConfirm, EgressConfirm, SupplyConfirm) - Guard LtvGauge filled-track math when currentLtv is 0 (div by zero) - Remove wrong tooltip on "Lending Markets" heading (was using utilisation tooltip, copy-paste slip) - Localize hardcoded "/ year" suffix in supply yearly earnings - Localize hardcoded "Full" badge in RepayConfirm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ral confirms Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
QAbot runs:
10/10 steps passed (chainflip-lending-revamp-ui fixture):
|
🤖 QA Test Report - PR #12189Tested: 2026-03-18 06:06 UTC Test Results: ✅ PASSEDScenario: Chainflip Lending Dashboard Revamp
UI VerificationHeader Stats (No Wallet):
Markets Table:
My Dashboard (Fresh Wallet):
Environment
Automated QA by ShapeShift QA Bot |
… spacing - Add ↑ prefix to Withdraw buttons matching Figma - EmptyState CTA buttons now solid (removed outline variant) - Next Steps card spacing increased for better breathing room Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/pages/ChainflipLending/components/Markets.tsx (1)
215-229: Consider lazy-mounting the tab panels.Chakra Tabs mounts every
TabPanelby default, so the hiddenDashboardandMarketsTablestill run their hooks and queries even when only one tab is visible. If that eager prefetch isn’t intentional,isLazywithlazyBehavior='keepMounted'keeps the first paint lighter without remounting a visited tab.♻️ Suggested change
- <Tabs index={tabIndex} onChange={setTabIndex} variant='soft-rounded' colorScheme='blue'> + <Tabs + index={tabIndex} + onChange={setTabIndex} + variant='soft-rounded' + colorScheme='blue' + isLazy + lazyBehavior='keepMounted' + >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/Markets.tsx` around lines 215 - 229, The Tabs component currently mounts all TabPanel children (Dashboard and MarketsTable) eagerly, causing their hooks/queries to run even when hidden; update the Tabs usage (the Tabs element that controls tabIndex and setTabIndex) to enable lazy mounting by adding isLazy and set lazyBehavior='keepMounted' so panels mount only when first shown but stay mounted on revisit, ensuring Dashboard and MarketsTable are not initialized until their tab is viewed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx`:
- Around line 206-207: The current early-return hides the Next Steps card
whenever !hasFreeBalance even if some steps (e.g., borrow when hasCollateral &&
!hasLoans) are still actionable; change the condition so the card is only hidden
when the user has completed everything. Replace the line using
hasFreeBalance/hasSupply/hasCollateral/hasLoans with a single check that returns
null only when hasSupply && hasCollateral && hasLoans, so that zero free balance
alone does not suppress actionable steps like Borrow.
---
Nitpick comments:
In `@src/pages/ChainflipLending/components/Markets.tsx`:
- Around line 215-229: The Tabs component currently mounts all TabPanel children
(Dashboard and MarketsTable) eagerly, causing their hooks/queries to run even
when hidden; update the Tabs usage (the Tabs element that controls tabIndex and
setTabIndex) to enable lazy mounting by adding isLazy and set
lazyBehavior='keepMounted' so panels mount only when first shown but stay
mounted on revisit, ensuring Dashboard and MarketsTable are not initialized
until their tab is viewed.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1bc230cc-5127-4c49-8747-1e0c2f28af22
📒 Files selected for processing (14)
src/assets/translations/en/main.jsonsrc/pages/ChainflipLending/Pool/components/Borrow/BorrowConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/CollateralConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/LtvGauge.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/RepayConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Deposit/DepositConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Egress/EgressConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Supply/SupplyConfirm.tsxsrc/pages/ChainflipLending/Pool/components/Supply/SupplyInput.tsxsrc/pages/ChainflipLending/Pool/components/Withdraw/WithdrawConfirm.tsxsrc/pages/ChainflipLending/components/DashboardSections.tsxsrc/pages/ChainflipLending/components/DashboardSidebar.tsxsrc/pages/ChainflipLending/components/InitView.tsxsrc/pages/ChainflipLending/components/Markets.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
- src/pages/ChainflipLending/components/DashboardSections.tsx
- src/assets/translations/en/main.json
- src/pages/ChainflipLending/Pool/components/Deposit/DepositConfirm.tsx
…hite totals - Empty section cards (Supplied, Collateral, Borrowed) now have dashed borders when no data, matching Figma empty state styling - Withdraw button changed from ghost to outline variant with ↑ prefix - Section total fiat values now white (removed text.subtle) for prominence - Added Loan Health bar and dashed border steps to revamp-ui fixture Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/pages/ChainflipLending/components/DashboardSidebar.tsx (1)
206-207:⚠️ Potential issue | 🟠 MajorEarly return hides Borrow CTA when user has collateral but no free balance
The
!hasFreeBalancecondition hides the entire card, suppressing the valid path at line 263 wherehasCollateral && !hasLoansshould show the Borrow button. A user who deposited all their free balance as collateral won't see the Borrow CTA.💡 Proposed fix
- // Hide when user has everything or no free balance - if (!hasFreeBalance || (hasSupply && hasCollateral && hasLoans)) return null + // Hide only when all tracked steps are completed + if (hasSupply && hasCollateral && hasLoans) return null🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx` around lines 206 - 207, The early return currently uses "!hasFreeBalance" which hides the card even when the user has collateral but no loans (the scenario that should show the Borrow CTA). Update the conditional in the DashboardSidebar component so the card is only hidden when there is no free balance AND it's not the special case of "hasCollateral && !hasLoans"; e.g. replace the "!hasFreeBalance" check with a combined check that allows rendering when (hasCollateral && !hasLoans), keeping the existing full-hide condition "(hasSupply && hasCollateral && hasLoans)" intact. Target the conditional that currently reads "if (!hasFreeBalance || (hasSupply && hasCollateral && hasLoans)) return null" and change it to allow the collateral-without-loans path.
🧹 Nitpick comments (1)
src/pages/ChainflipLending/components/DashboardSidebar.tsx (1)
55-58: Consider handling negative available borrowing powerWhen collateral value drops (e.g., due to price movements),
totalBorrowedFiatcan exceedmaxBorrow, resulting in a negativeavailablevalue. Displaying a negative amount withgreen.500color may mislead users about their actual risk status.💡 Proposed fix to clamp and adjust color
const available = useMemo( - () => bnOrZero(maxBorrow).minus(totalBorrowedFiat).toFixed(2), + () => { + const rawAvailable = bnOrZero(maxBorrow).minus(totalBorrowedFiat) + return rawAvailable.lt(0) ? '0' : rawAvailable.toFixed(2) + }, [maxBorrow, totalBorrowedFiat], )Alternatively, if showing the negative is intentional, consider changing the color to reflect the risk:
- <Amount.Fiat value={available} fontSize='lg' fontWeight='bold' color='green.500' /> + <Amount.Fiat + value={available} + fontSize='lg' + fontWeight='bold' + color={bnOrZero(available).lt(0) ? 'red.500' : 'green.500'} + />Also applies to: 95-95
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx` around lines 55 - 58, The computed available borrowing power (variable available inside the useMemo using maxBorrow and totalBorrowedFiat) can go negative when collateral falls; update the logic to clamp the displayed available value (e.g., Math.max(bnOrZero(maxBorrow).minus(totalBorrowedFiat), 0).toFixed(2) or similar) and adjust the UI color based on sign (use the existing display path that consumes available to render green for positive/zero and a warning color like red/orange when negative), or if you prefer to show the negative value keep the real negative figure but change the color logic to read the numeric sign from the un-clamped bnOrZero(...) result to avoid misleading green styling for risky negative balances.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx`:
- Around line 206-207: The early return currently uses "!hasFreeBalance" which
hides the card even when the user has collateral but no loans (the scenario that
should show the Borrow CTA). Update the conditional in the DashboardSidebar
component so the card is only hidden when there is no free balance AND it's not
the special case of "hasCollateral && !hasLoans"; e.g. replace the
"!hasFreeBalance" check with a combined check that allows rendering when
(hasCollateral && !hasLoans), keeping the existing full-hide condition
"(hasSupply && hasCollateral && hasLoans)" intact. Target the conditional that
currently reads "if (!hasFreeBalance || (hasSupply && hasCollateral &&
hasLoans)) return null" and change it to allow the collateral-without-loans
path.
---
Nitpick comments:
In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx`:
- Around line 55-58: The computed available borrowing power (variable available
inside the useMemo using maxBorrow and totalBorrowedFiat) can go negative when
collateral falls; update the logic to clamp the displayed available value (e.g.,
Math.max(bnOrZero(maxBorrow).minus(totalBorrowedFiat), 0).toFixed(2) or similar)
and adjust the UI color based on sign (use the existing display path that
consumes available to render green for positive/zero and a warning color like
red/orange when negative), or if you prefer to show the negative value keep the
real negative figure but change the color logic to read the numeric sign from
the un-clamped bnOrZero(...) result to avoid misleading green styling for risky
negative balances.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 09fe4dde-85f4-470e-b734-4e41b688efcd
📒 Files selected for processing (1)
src/pages/ChainflipLending/components/DashboardSidebar.tsx
|
btw @NeOMakinG did some more visual polish to make things even closer to the Figma:
Latest QAbot run (post-polish): https://qabot-kappa.vercel.app/runs/0449d471-a1bf-47a1-adfa-b95c9ac7b4e6 All 6 steps passed. See earlier runs too: |
…details - Repay button uses ↻ prefix instead of ↑ (not a withdraw action) - "Start Liquidation" link now has → arrow suffix matching Figma - Secondary action prefix is now configurable per section Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@e2e/fixtures/chainflip-lending-revamp-ui.yaml`:
- Around line 32-33: Update the fixture wording to match the UI polish by
removing or replacing stale style adjectives ("ghost"/"outline") and using the
current button descriptors or neutral labels; specifically edit the sentence
containing "Blue filled \"+ Deposit\" button and ghost \"Withdraw\" button in
Free Balance header" to instead reference the current style (e.g., "Blue \"+
Deposit\" button and \"Withdraw\" button" or the new style name used in the app)
and make the same change for the similar text at the other occurrence (the block
mentioning "Supply" and "Add Collateral") so the expected strings "+ Deposit",
"Withdraw", "Supply", and "Add Collateral" match the app's latest wording and
style terminology.
In `@src/pages/ChainflipLending/components/DashboardSections.tsx`:
- Around line 207-208: The column headers rendered with RawText (e.g., the
hardcoded "Asset" and "Balance" strings and the similar literals at the other
noted locations) should be localized: import or use the existing translation
helper (e.g., useTranslation()/t or i18n.t) and replace the hardcoded RawText
contents with translated keys (e.g., t('dashboard.asset'),
t('dashboard.balance')) and add those keys to the translation files; update all
occurrences referenced (the RawText usages at the other ranges) so the dashboard
shows only translated strings.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 212924d7-4ba3-4a89-8bb8-f372fc226851
📒 Files selected for processing (3)
.gemini/settings.jsone2e/fixtures/chainflip-lending-revamp-ui.yamlsrc/pages/ChainflipLending/components/DashboardSections.tsx
|
btw @NeOMakinG did another round of visual polish + comprehensive testing including the full lending lifecycle (add collateral → borrow → LTV bar verification → repay flow). See comprehensive QAbot run: https://qabot-kappa.vercel.app/runs/375d7b75-a5c2-41f1-be22-cbce7354996d 19/19 steps passed covering:
Latest polish (pass 5):
|
|
@NeOMakinG GM, I'm Gemini, Beep Boop 🤖, I'm a bot who does the UI thing, and I did a super deep thorough visual QA pass against the Figma mocks using MCP. What do you think? Regarding your question: Yes, the debt being in token terms (USDC/USDT) is correct. In lending protocols, your debt obligation is the actual token amount you borrowed plus interest, while the fiat (user currency) value will fluctuate with the market. I've ensured the UI clearly displays both the precise crypto amount and its fiat equivalent to keep things perfectly clear for the user. Here is a summary of the thorough visual QA pass I completed: 🛠️ What I Fixed & Improved:
✅ What I Confirmed Looks Good Already:
Everything is pushed and the codebase is passing |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
src/pages/ChainflipLending/components/DashboardSidebar.tsx (1)
208-209:⚠️ Potential issue | 🟠 MajorNext Steps card hides valid borrow action when free balance is zero.
The condition
!hasFreeBalance || (hasSupply && hasCollateral && hasLoans)incorrectly hides the card when the user has no free balance but has collateral without loans. In this case, the user should still see the "Borrow" CTA (thehasCollateral && !hasLoansbranch at line 265).🐛 Proposed fix
- // Hide when user has everything or no free balance - if (!hasFreeBalance || (hasSupply && hasCollateral && hasLoans)) return null + // Hide only when all tracked steps are completed + if (hasSupply && hasCollateral && hasLoans) return null🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx` around lines 208 - 209, The sidebar currently returns null when !hasFreeBalance, which also hides the valid "Borrow" CTA for users who have collateral and no loans; update the condition in DashboardSidebar to only hide when the user has no free balance AND does not have collateral-only borrow eligibility. Replace the line "if (!hasFreeBalance || (hasSupply && hasCollateral && hasLoans)) return null" with a condition that preserves the borrow case, e.g. return null only when ((!hasFreeBalance && !(hasCollateral && !hasLoans)) || (hasSupply && hasCollateral && hasLoans)), so the branch for hasCollateral && !hasLoans still renders the Next Steps card.
🧹 Nitpick comments (3)
src/pages/ChainflipLending/Pool/components/Borrow/BorrowInput.tsx (1)
36-37: Avoid duplicating the risky LTV fallback constant across borrow components.
DEFAULT_RISKY_LTVis defined here and also insrc/pages/ChainflipLending/Pool/components/Borrow/LtvGauge.tsx. Keeping it in one shared constant avoids drift between threshold logic and gauge rendering.♻️ Suggested shared-constant extraction
-const DEFAULT_RISKY_LTV = 0.8 +import { DEFAULT_RISKY_LTV } from '@/pages/ChainflipLending/constants'// src/pages/ChainflipLending/constants.ts export const DEFAULT_RISKY_LTV = 0.8-const DEFAULT_RISKY_LTV = 0.8 +import { DEFAULT_RISKY_LTV } from '@/pages/ChainflipLending/constants'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/Pool/components/Borrow/BorrowInput.tsx` around lines 36 - 37, Remove the duplicated DEFAULT_RISKY_LTV constant from BorrowInput and LtvGauge and extract it to a single shared export (e.g., export const DEFAULT_RISKY_LTV = 0.8) in a new shared constants module; then replace the local definitions by importing DEFAULT_RISKY_LTV into both BorrowInput.tsx and LtvGauge.tsx so both components reference the same symbol and avoid drift.src/pages/ChainflipLending/components/Markets.tsx (1)
218-243: Consider extracting repeated Tab styling to reduce duplication.Both Tab components share identical styling props. Extracting to a shared style object would reduce duplication and ease future styling changes.
💅 Proposed refactor
+const tabStyles = { + px: 0, + py: 2, + color: 'text.subtle', + fontWeight: 'bold', + _selected: { + color: 'text.base', + borderBottomWidth: 2, + borderColor: 'text.base', + }, +} + <TabList data-testid='chainflip-lending-tabs' gap={6}> - <Tab - px={0} - py={2} - color='text.subtle' - fontWeight='bold' - _selected={{ - color: 'text.base', - borderBottomWidth: 2, - borderColor: 'text.base', - }} - > + <Tab {...tabStyles}> {translate('chainflipLending.myDashboard')} </Tab> - <Tab - px={0} - py={2} - color='text.subtle' - fontWeight='bold' - _selected={{ - color: 'text.base', - borderBottomWidth: 2, - borderColor: 'text.base', - }} - > + <Tab {...tabStyles}> {translate('chainflipLending.markets')} </Tab> </TabList>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/Markets.tsx` around lines 218 - 243, Both Tab components in Markets.tsx repeat identical props; extract the shared props into a single reusable style to reduce duplication. Create a const (e.g., tabProps or tabStyle) or a small wrapper component (e.g., StyledTab) and use it for both Tab instances so the shared props (px, py, color, fontWeight, _selected) are defined in one place; update the two Tab usages to spread or use that shared identifier to keep behavior identical.src/pages/ChainflipLending/components/DashboardSections.tsx (1)
314-321: DuplicatepoolsByAssetIdlogic can be extracted to a shared hook or utility.The same reduce pattern to create a pool lookup map is duplicated in
SuppliedSection(lines 314-321) andBorrowedSection(lines 592-599). Consider extracting this to a custom hook or adding apoolsByAssetIdproperty touseChainflipLendingPools.♻️ Option 1: Extract to hook
// In useChainflipLendingPools.ts export const useChainflipLendingPools = () => { // ... existing logic ... const poolsByAssetId = useMemo( () => pools.reduce<Partial<Record<AssetId, ChainflipLendingPoolWithFiat>>>((acc, pool) => { if (pool.assetId) acc[pool.assetId] = pool return acc }, {}), [pools], ) return { pools, poolsByAssetId, isLoading } }Also applies to: 592-599
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/ChainflipLending/components/DashboardSections.tsx` around lines 314 - 321, Extract the duplicated reduce logic that builds poolsByAssetId into the shared data layer: add a memoized poolsByAssetId property to the existing useChainflipLendingPools hook (or create a small util used by both) so SuppliedSection and BorrowedSection can consume it directly; specifically, move the reduce from components where poolsByAssetId is currently computed into useChainflipLendingPools and return { pools, poolsByAssetId, ... } (or export a helper) and update SuppliedSection and BorrowedSection to use the new property instead of re-creating the map.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/pages/ChainflipLending/components/DashboardSidebar.tsx`:
- Around line 208-209: The sidebar currently returns null when !hasFreeBalance,
which also hides the valid "Borrow" CTA for users who have collateral and no
loans; update the condition in DashboardSidebar to only hide when the user has
no free balance AND does not have collateral-only borrow eligibility. Replace
the line "if (!hasFreeBalance || (hasSupply && hasCollateral && hasLoans))
return null" with a condition that preserves the borrow case, e.g. return null
only when ((!hasFreeBalance && !(hasCollateral && !hasLoans)) || (hasSupply &&
hasCollateral && hasLoans)), so the branch for hasCollateral && !hasLoans still
renders the Next Steps card.
---
Nitpick comments:
In `@src/pages/ChainflipLending/components/DashboardSections.tsx`:
- Around line 314-321: Extract the duplicated reduce logic that builds
poolsByAssetId into the shared data layer: add a memoized poolsByAssetId
property to the existing useChainflipLendingPools hook (or create a small util
used by both) so SuppliedSection and BorrowedSection can consume it directly;
specifically, move the reduce from components where poolsByAssetId is currently
computed into useChainflipLendingPools and return { pools, poolsByAssetId, ... }
(or export a helper) and update SuppliedSection and BorrowedSection to use the
new property instead of re-creating the map.
In `@src/pages/ChainflipLending/components/Markets.tsx`:
- Around line 218-243: Both Tab components in Markets.tsx repeat identical
props; extract the shared props into a single reusable style to reduce
duplication. Create a const (e.g., tabProps or tabStyle) or a small wrapper
component (e.g., StyledTab) and use it for both Tab instances so the shared
props (px, py, color, fontWeight, _selected) are defined in one place; update
the two Tab usages to spread or use that shared identifier to keep behavior
identical.
In `@src/pages/ChainflipLending/Pool/components/Borrow/BorrowInput.tsx`:
- Around line 36-37: Remove the duplicated DEFAULT_RISKY_LTV constant from
BorrowInput and LtvGauge and extract it to a single shared export (e.g., export
const DEFAULT_RISKY_LTV = 0.8) in a new shared constants module; then replace
the local definitions by importing DEFAULT_RISKY_LTV into both BorrowInput.tsx
and LtvGauge.tsx so both components reference the same symbol and avoid drift.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6d0d1fc5-84eb-4264-9d9c-3698a1bd60ef
📒 Files selected for processing (10)
.gitignoresrc/assets/translations/en/main.jsonsrc/pages/ChainflipLending/Pool/components/Borrow/BorrowInput.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/LtvGauge.tsxsrc/pages/ChainflipLending/Pool/components/Borrow/RepayInput.tsxsrc/pages/ChainflipLending/components/ChainflipLendingHeader.tsxsrc/pages/ChainflipLending/components/DashboardSections.tsxsrc/pages/ChainflipLending/components/DashboardSidebar.tsxsrc/pages/ChainflipLending/components/LoanHealth.tsxsrc/pages/ChainflipLending/components/Markets.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- src/pages/ChainflipLending/components/LoanHealth.tsx
- Fix Next Steps card hiding when no free balance but collateral exists - Localize hardcoded column headers in dashboard sections - Fix e2e fixture button style descriptions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description
Revamps the Chainflip Lending UI dashboard to be closer to the Figma designs. Takes the good ideas from product's designs and implements them properly, no fox given about the parts that are still half-baked on the Figma side.
What's new:
What's NOT in this PR (product work still WIP on Figma, no fox given):
There'll be follow-ups whenever things evolve on product side.
Issue (if applicable)
Related to the Chainflip Lending dashboard designs shared by 0xFBL
Risk
Low. Behind
VITE_FEATURE_CHAINFLIP_LENDINGfeature flag (dev=true, prod=false). No existing flows affected.Testing
Engineering
VITE_FEATURE_CHAINFLIP_LENDING=true/chainflip-lendingOperations
Screenshots (if applicable)
QAbot run: 10/10 steps passed (chainflip-lending-revamp-ui fixture)
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Improvements
Tests