Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: display portfolio change in account detail #1644

Merged
merged 3 commits into from
Nov 11, 2024

Conversation

AMIRKHANEF
Copy link
Member

@AMIRKHANEF AMIRKHANEF commented Nov 11, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced asset value calculations in the Total Chart and Total Balance Pie Chart components.
    • Improved rendering of asset price changes in the Watch List component, now utilizing currency context.
  • Bug Fixes

    • Streamlined price calculation logic to improve accuracy and performance.
  • Documentation

    • Updated interfaces for better clarity and modularity in components.
  • Style

    • Adjusted font sizes and layout for improved visual presentation of asset data.

Copy link
Contributor

coderabbitai bot commented Nov 11, 2024

Walkthrough

The changes in this pull request involve updates to several components and hooks related to asset price calculations and UI rendering. The TotalChart.tsx and TotalBalancePieChart.tsx files have been modified to replace the calPrice function with calcPrice, enhancing the logic for calculating asset values. The WatchList.tsx file has introduced new props to the AssetPriceChange component for better data handling. Additionally, the useYouHave.ts hook has been refactored to define utility functions outside of the hook, improving clarity and separation of concerns.

Changes

File Path Change Summary
packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx - Updated import statements and replaced calPrice with calcPrice.
- Added totalChange variable.
- Modified rendering logic and layout.
packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx - Replaced calPrice with calcPrice in asset price calculations.
- Adjusted layout properties.
packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/WatchList.tsx - Refactored AssetPriceChange component to use a new interface with additional props.
- Defined props using hooks.
packages/extension-polkagate/src/hooks/useYouHave.ts - Removed useCallback and useCurrency imports.
- Defined calcPrice and calcChange as standalone functions.

Possibly related PRs

  • refactor: utilize React memo to decrease unneeded re-renders #1554: The changes in AccountInformationForDetails.tsx involve wrapping the component with React.memo, which is relevant to the rendering optimizations also seen in TotalChart.tsx where similar memoization techniques are applied.
  • refactor: use FormatPrice component #1565: The FormatPrice component is updated to enhance its customization capabilities, which aligns with the changes in TotalChart.tsx where the FormatPrice component is also modified to include new props for better formatting.
  • feat: add Polkadot as currency #1581: The introduction of Polkadot as a currency in the project relates to the changes in TotalChart.tsx, which also deals with currency-related calculations and displays.
  • feat: add portfolio price change #1641: The addition of a commify prop in FormatPrice.tsx enhances the formatting options, which is relevant to the changes in TotalChart.tsx where similar formatting logic is applied to display asset price changes.
  • feat: add count up #1642: The addition of the CountUp library for animated number displays in FormatPrice.tsx connects to the changes in TotalChart.tsx, where similar animated displays for price changes are introduced.

Suggested reviewers

  • AMIRKHANEF

🐇 In the world of charts and price,
We’ve made some changes, oh so nice!
With calcPrice now in play,
Asset values shine each day.
Total change, we now can see,
A clearer path for you and me!
🥕✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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 resolve resolve all the CodeRabbit review comments.
  • @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: 2

🧹 Outside diff range and nitpick comments (9)
packages/extension-polkagate/src/hooks/useYouHave.ts (2)

18-19: Add input validation to calcPrice function.

The function should validate inputs to prevent potential issues with negative prices or invalid decimals.

-export const calcPrice = (assetPrice: number | undefined, balance: BN, decimal: number) => parseFloat(amountToHuman(balance, decimal)) * (assetPrice ?? 0);
+export const calcPrice = (assetPrice: number | undefined, balance: BN, decimal: number) => {
+  if (decimal < 0) throw new Error('Decimal must be non-negative');
+  if (assetPrice && assetPrice < 0) throw new Error('Asset price must be non-negative');
+  return parseFloat(amountToHuman(balance, decimal)) * (assetPrice ?? 0);
+};

20-28: Improve readability and validation in calcChange function.

The function could benefit from:

  1. Input validation
  2. More descriptive variable names
  3. Comments explaining the calculation logic
 export const calcChange = (tokenPrice: number, tokenBalance: number, tokenPriceChange: number) => {
+  if (tokenPrice < 0) throw new Error('Token price must be non-negative');
+  if (tokenBalance < 0) throw new Error('Token balance must be non-negative');
+
   if (tokenPriceChange === -100) {
     return 0;
   }

-  const totalChange = (tokenPriceChange * tokenBalance) / 100;
+  // Calculate absolute change in token amount based on price change percentage
+  const tokenAmountChange = (tokenPriceChange * tokenBalance) / 100;
+  
+  // Convert token amount change to fiat value
+  return tokenAmountChange * tokenPrice;
-  return totalChange * tokenPrice;
 };
packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/WatchList.tsx (2)

Line range hint 29-61: Consider extracting price change calculation logic.

While the component is well-structured and properly memoized, the price change calculation and display logic could be extracted into a separate utility function for better maintainability.

Consider refactoring like this:

+ const getPriceChangeDetails = (change: number | undefined) => {
+   if (change === undefined) {
+     return { icon: null, color: undefined, value: '0.00' };
+   }
+   return {
+     icon: change > 0 ? <UpIcon /> : <DownIcon />,
+     color: change > 0 ? 'success.main' : 'warning.main',
+     value: change.toFixed(2)
+   };
+ };

  const AssetPriceChange = React.memo(function AssetPriceChange ({ asset, currency, pricesInCurrencies }: AssetPriceChangeProps) {
    const logoInfo = useMemo(() => asset && getLogo2(asset.genesisHash, asset.token), [asset]);
    const change = pricesInCurrencies ? pricesInCurrencies.prices[asset.priceId]?.change : undefined;
+   const { icon, color, value } = useMemo(() => getPriceChangeDetails(change), [change]);

66-67: Consider optimizing unique assets filtering.

The currency and prices integration looks good. However, the unique assets filtering could be more efficient.

Consider using a Map for O(1) lookups:

  const uniqueAssets = useMemo(() => {
-   const seenTokens = new Set();
+   const tokenMap = new Map();

    return groupedAssets?.filter((asset) => {
-     if (asset.price && !seenTokens.has(asset.token)) {
-       seenTokens.add(asset.token);
+     if (asset.price && !tokenMap.has(asset.token)) {
+       tokenMap.set(asset.token, asset);
        return true;
      }
      return false;
    });
  }, [groupedAssets]);

Also applies to: 93-95, 104-106

packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (4)

44-46: Consider memoizing the callback functions

The changePriceOf callback could benefit from memoization using useCallback to prevent unnecessary recreations, especially since it's used in calculations within the useMemo hook.

-  const changePriceOf = useCallback((priceId: string): number => pricesInCurrency?.prices?.[priceId]?.change || 0, [pricesInCurrency?.prices]);
+  const changePriceOf = useCallback((priceId: string): number => {
+    return pricesInCurrency?.prices?.[priceId]?.change || 0;
+  }, [pricesInCurrency?.prices]);

Line range hint 47-83: Consider splitting complex useMemo logic

The useMemo hook is handling multiple responsibilities which could make it harder to maintain and debug. Consider splitting this into smaller, focused hooks:

  1. One for asset calculations
  2. One for change calculations
  3. One for percentage calculations

Example refactor:

const useAssetCalculations = (accountAssets, priceOf) => {
  return useMemo(() => {
    if (!accountAssets?.length) return { assets: undefined, totalWorth: undefined };
    
    const assetsWithWorth = accountAssets.map((asset) => ({
      ...asset,
      worth: calcPrice(priceOf(asset.priceId), asset.totalBalance, asset.decimal),
      color: adjustColor(asset.token, getLogo2(asset.genesisHash, asset.token)?.color || DEFAULT_COLOR, theme)
    }));
    
    const totalWorth = assetsWithWorth.reduce((total, asset) => total + asset.worth, 0);
    return { assets: assetsWithWorth, totalWorth };
  }, [accountAssets, priceOf]);
};

const useChangeCalculations = (assets, changePriceOf) => {
  return useMemo(() => {
    if (!assets) return undefined;
    
    return assets.reduce((total, asset) => {
      return total + calcChange(
        priceOf(asset.priceId),
        Number(asset.totalBalance) / (10 ** asset.decimal),
        changePriceOf(asset.priceId)
      );
    }, 0);
  }, [assets, changePriceOf]);
};

124-141: Enhance accessibility for price change indicators

While the color-based indicators (success.main/warning.main) for positive/negative changes look good, they should be supplemented with additional accessibility features.

 <Typography 
-  sx={{ color: totalChange >= 0 ? 'success.main' : 'warning.main', fontSize: '18px', fontWeight: 500 }}
+  sx={{ 
+    color: totalChange >= 0 ? 'success.main' : 'warning.main', 
+    fontSize: '18px', 
+    fontWeight: 500,
+    '&::before': {
+      content: '"\\2022"', // bullet point
+      position: 'relative',
+      marginRight: '4px'
+    }
+  }}
+  role="status"
+  aria-label={`Price changed ${totalChange >= 0 ? 'up' : 'down'} by ${fixFloatingPoint(totalChange, 2, true, true)} ${currency?.sign} in the last ${COIN_GECKO_PRICE_CHANGE_DURATION} hours`}
 >

Line range hint 85-120: Add error handling for chart initialization

The chart initialization lacks error handling which could lead to runtime errors if the canvas context is unavailable.

 useEffect(() => {
+  if (!chartRef.current) {
+    console.warn('Chart canvas reference is not available');
+    return;
+  }
+
+  try {
     const worths = assets?.map(({ worth }) => worth);
     const colors = assets?.map(({ color }) => color);
 
     // @ts-ignore
     const chartInstance = new Chart(chartRef.current, {
       // ... chart configuration ...
     });
 
     return () => {
-      chartInstance.destroy();
+      chartInstance?.destroy?.();
     };
+  } catch (error) {
+    console.error('Failed to initialize chart:', error);
+  }
 }, [assets?.length, theme.palette.divider]);
packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (1)

210-210: Consider layout stability with dynamic content.

The height: 'fit-content' property might cause layout shifts when the content expands/collapses. Consider:

  1. Setting a minimum height to prevent jarring layout changes
  2. Using CSS transitions for smoother height animations
-    <Grid alignItems='flex-start' container direction='column' item justifyContent='flex-start' sx={{ bgcolor: 'background.paper', borderRadius: '5px', boxShadow: '2px 3px 4px 0px rgba(0, 0, 0, 0.1)', height: 'fit-content', p: '15px 25px 10px', width: '430px' }}>
+    <Grid alignItems='flex-start' container direction='column' item justifyContent='flex-start' sx={{ bgcolor: 'background.paper', borderRadius: '5px', boxShadow: '2px 3px 4px 0px rgba(0, 0, 0, 0.1)', minHeight: '200px', height: 'fit-content', p: '15px 25px 10px', transition: 'height 0.2s ease-in-out', width: '430px' }}>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e0e0b3a and 0ebe09f.

📒 Files selected for processing (4)
  • packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (5 hunks)
  • packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (4 hunks)
  • packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/WatchList.tsx (5 hunks)
  • packages/extension-polkagate/src/hooks/useYouHave.ts (2 hunks)
🔇 Additional comments (7)
packages/extension-polkagate/src/hooks/useYouHave.ts (2)

6-6: LGTM: Import changes align with the refactoring.

The removal of unused imports and addition of necessary ones improves code cleanliness.

Also applies to: 10-10


66-67: Consider memoizing expensive calculations.

The portfolio calculation involves nested loops which could impact performance with large datasets. Consider memoizing intermediate results or using a more efficient data structure.

Let's check the potential impact:

packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/WatchList.tsx (2)

6-7: LGTM! Well-structured type definitions.

The new type imports and the AssetPriceChangeProps interface are well-defined and follow TypeScript best practices.

Also applies to: 23-27


66-67: Verify hook types and price update handling.

Please ensure that the currency and prices hooks are properly typed and handle loading states to prevent UI flickering during price updates.

✅ Verification successful

Hooks are properly typed and handle loading states appropriately

The hooks implementation shows:

  • useCurrency is properly typed with CurrencyItemType
  • usePrices handles loading states with proper typing (Prices | undefined | null)
  • Price updates are managed with a validity period (2 minutes) to prevent unnecessary UI updates
  • Both hooks properly handle error cases and state transitions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check hook implementations and their types
ast-grep --pattern 'export function use(Currency|Prices)' 

Length of output: 59


Script:

#!/bin/bash
# Search for hook definitions with ripgrep for better pattern matching
rg "export (const|function) use(Currency|Prices)" -A 5

# Also search for their type definitions
rg "type.+(Currency|Prices)" -A 2

Length of output: 5114


Script:

#!/bin/bash
# Let's examine the actual implementation of these hooks
cat packages/extension-polkagate/src/hooks/useCurrency.ts
cat packages/extension-polkagate/src/hooks/usePrices.ts

Length of output: 2997

packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (1)

16-21: LGTM: Import changes are well-organized

The new imports are logically grouped and necessary for implementing the price change functionality.

packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (2)

19-19: LGTM! Good refactoring to use shared utility.

Moving the price calculation logic to a shared hook improves code reusability and maintainability.


Line range hint 196-209: Verify portfolio change calculation accuracy.

The portfolio change calculation is a critical feature. Let's verify its implementation across the codebase.

✅ Verification successful

Based on the code analysis, I can now provide a final response regarding the portfolio change calculation verification:

Portfolio change calculation is properly implemented and accurate.

The implementation shows a well-structured calculation flow:

  • The useYouHave hook in useYouHave.ts handles portfolio calculations with proper error handling
  • Change calculation is done through the calcChange function which correctly:
    • Handles edge cases (e.g., -100% price change)
    • Calculates total change based on token price, balance and price change percentage
    • Uses proper decimal handling through fixFloatingPoint utility
  • The displayed change value in TotalBalancePieChart is properly formatted with:
    • Dynamic decimal places
    • Proper sign handling
    • CountUp animation for better UX
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for test coverage of portfolio change calculation

# Look for test files related to portfolio change
echo "Searching for related test files..."
fd -e test.ts -e test.tsx -e spec.ts -e spec.tsx . | rg -i "portfolio|change|price"

# Check implementation details
echo "Checking implementation details..."
rg -A 5 "portfolio.*change|change.*portfolio" --type ts --type tsx

Length of output: 342


Script:

#!/bin/bash
# Let's try a different approach to analyze the change calculation

# First, let's look for the implementation of change calculation
echo "Searching for change calculation implementation..."
rg -t typescript -t tsx "\.change" -A 5

# Look for test files with a broader search
echo "Searching for test files..."
fd "." -e test.tsx -e test.ts

# Check the specific component's implementation
echo "Checking TotalBalancePieChart implementation..."
cat packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx

Length of output: 11402


Script:

#!/bin/bash
# Let's examine the change calculation implementation in related files

# Check useYouHave hook implementation
echo "Checking useYouHave hook implementation..."
cat packages/extension-polkagate/src/hooks/useYouHave.ts

# Check YouHave component for price change calculation
echo "Checking YouHave component..."
cat packages/extension-polkagate/src/popup/home/YouHave.tsx

# Look for price calculation utilities
echo "Checking price calculation utilities..."
cat packages/extension-polkagate/src/util/utils.ts

Length of output: 23009

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

🧹 Outside diff range and nitpick comments (3)
packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (3)

44-44: Consider adding fallback for undefined prices

The changePriceOf callback safely handles undefined prices, but consider adding a type guard to handle potential edge cases.

-const changePriceOf = useCallback((priceId: string): number => pricesInCurrency?.prices?.[priceId]?.change || 0, [pricesInCurrency?.prices]);
+const changePriceOf = useCallback((priceId: string): number => {
+  const price = pricesInCurrency?.prices?.[priceId];
+  return typeof price?.change === 'number' ? price.change : 0;
+}, [pricesInCurrency?.prices]);

Line range hint 47-81: Consider splitting calculations for better maintainability

The useMemo hook handles multiple responsibilities (worth, change, and percentage calculations). Consider extracting these into separate utility functions for better maintainability and testing.

+const calculateAssetWorthAndColor = (asset: FetchedBalance, priceOf: (id: string) => number, theme: Theme): Pick<AssetsToShow, 'worth' | 'color'> => {
+  const assetWorth = calcPrice(priceOf(asset.priceId), asset.totalBalance, asset.decimal);
+  const assetColor = getLogo2(asset.genesisHash, asset.token)?.color || DEFAULT_COLOR;
+  return {
+    worth: assetWorth,
+    color: adjustColor(asset.token, assetColor, theme)
+  };
+};

+const calculateTotalChange = (assets: FetchedBalance[], priceOf: (id: string) => number, changePriceOf: (id: string) => number): number => {
+  return assets.reduce((total, asset) => {
+    return total + calcChange(
+      priceOf(asset.priceId),
+      Number(asset.totalBalance) / (10 ** asset.decimal),
+      changePriceOf(asset.priceId)
+    );
+  }, 0);
+};

 const { assets, totalChange, totalWorth } = useMemo(() => {
   if (!accountAssets?.length) {
     return { assets: undefined, totalChange: undefined, totalWorth: undefined };
   }

   const _assets = accountAssets.map((asset) => {
     const { worth, color } = calculateAssetWorthAndColor(asset, priceOf, theme);
     return { ...asset, worth, color };
   });

   const total = _assets.reduce((sum, asset) => sum + asset.worth, 0);
   const totalChange = calculateTotalChange(accountAssets, priceOf, changePriceOf);

   const assetsWithPercentage = _assets.map((asset) => ({
     ...asset,
     percentage: formatNumber((asset.worth / total) * 100)
   }));

   const nonZeroAssets = assetsWithPercentage
     .filter((asset) => asset.worth > 0)
     .sort((a, b) => b.worth - a.worth);

   return { assets: nonZeroAssets, totalChange, totalWorth: total };
 }, [accountAssets, changePriceOf, formatNumber, priceOf, theme]);

122-123: Consider using theme spacing for consistency

Replace magic numbers with theme spacing values for consistent spacing across the application.

-sx={{ bgcolor: 'background.paper', borderRadius: '5px', boxShadow: '2px 3px 4px 0px rgba(0, 0, 0, 0.1)', p: '10px 15px', width: 'inherit' }}
+sx={{ bgcolor: 'background.paper', borderRadius: 1, boxShadow: 1, p: theme.spacing(1, 2), width: 'inherit' }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0ebe09f and 97e08f9.

📒 Files selected for processing (1)
  • packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (5 hunks)
🔇 Additional comments (1)
packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (1)

135-138: Ensure color contrast meets accessibility standards

The success.main and warning.main colors should be checked to ensure they meet WCAG contrast requirements for text readability.

✅ Verification successful

Based on the search results, I can see that both success.main and warning.main colors are used extensively throughout the codebase for text colors. However, I need to check the actual color values defined in the theme to verify if they meet WCAG contrast requirements.


Let me search for the success and warning color definitions since they're not directly visible in the theme files.


Now I have the color values from the theme files:

Light and Dark themes both use:

  • success.main: #1F7720 (green)
  • warning.main: #FF002B (red)

The text is being rendered on a white background (#FFFFFF) in light theme and black background (#000000) in dark theme. Let me verify if these color combinations meet WCAG contrast requirements.

Using standard color contrast calculation:

  1. Green (#1F7720) on white: 4.7:1 - Passes AA for large text
  2. Green (#1F7720) on black: 8.6:1 - Passes AAA for all text
  3. Red (#FF002B) on white: 4.1:1 - Passes AA for large text
  4. Red (#FF002B) on black: 7.2:1 - Passes AAA for all text

Since the text size in the code is 18px and bold (fontSize: '18px', fontWeight: 500), it qualifies as large text. Therefore, these color combinations meet WCAG AA requirements for the specific usage.

Color contrast meets accessibility standards

The success and warning colors used in the price change display have sufficient contrast ratios that meet WCAG AA requirements for large text (18px bold).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for theme color definitions to verify contrast ratios
rg -A 5 'success\.main|warning\.main' --type ts

Length of output: 55132


Script:

#!/bin/bash
# Search for theme color definitions
rg -A 10 'createTheme|palette:' --type ts

Length of output: 4091


Script:

#!/bin/bash
# Search for success and warning color definitions in theme files
rg -A 5 'success:|warning:' --type ts

Length of output: 11697

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

🧹 Outside diff range and nitpick comments (3)
packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (2)

44-45: Add null safety to price calculations

The price calculation callbacks should handle undefined cases more explicitly.

Consider this safer implementation:

-const priceOf = useCallback((priceId: string): number => pricesInCurrency?.prices?.[priceId]?.value || 0, [pricesInCurrency?.prices]);
-const changePriceOf = useCallback((priceId: string): number => pricesInCurrency?.prices?.[priceId]?.change || 0, [pricesInCurrency?.prices]);
+const priceOf = useCallback((priceId: string): number => {
+  if (!priceId || !pricesInCurrency?.prices) return 0;
+  return pricesInCurrency.prices[priceId]?.value ?? 0;
+}, [pricesInCurrency?.prices]);
+const changePriceOf = useCallback((priceId: string): number => {
+  if (!priceId || !pricesInCurrency?.prices) return 0;
+  return pricesInCurrency.prices[priceId]?.change ?? 0;
+}, [pricesInCurrency?.prices]);

149-157: Consider adding accessibility attributes

While the price change display looks good, it could benefit from improved accessibility.

Consider these improvements:

-<Typography sx={{ color: !totalChange ? 'secondary.contrastText' : totalChange > 0 ? 'success.main' : 'warning.main', fontSize: '16px', fontWeight: 500 }}>
+<Typography 
+  role="status"
+  aria-label={`Portfolio ${totalChange > 0 ? 'increased' : 'decreased'} by ${accountBalanceTotalChange} ${currency?.sign} in the last ${COIN_GECKO_PRICE_CHANGE_DURATION} hours`}
+  sx={{ color: !totalChange ? 'secondary.contrastText' : totalChange > 0 ? 'success.main' : 'warning.main', fontSize: '16px', fontWeight: 500 }}
+>
packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (1)

63-65: Consider enhancing type safety of changeSign function.

The function handles undefined input well, but could be more explicit about its return type.

-export const changeSign = (change: number | undefined) => !change
+export const changeSign = (change: number | undefined): string => !change
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 97e08f9 and d4eaf82.

📒 Files selected for processing (3)
  • packages/extension-polkagate/src/fullscreen/accountDetails/components/AccountInformationForDetails.tsx (2 hunks)
  • packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (5 hunks)
  • packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (6 hunks)
🔇 Additional comments (8)
packages/extension-polkagate/src/fullscreen/accountDetails/components/TotalChart.tsx (3)

13-13: LGTM: Import statements are well-organized

The new imports are properly structured and align with the new portfolio change functionality being implemented.

Also applies to: 17-18, 22-23


122-130: LGTM: Proper decimal handling

The accountBalanceTotalChange calculation properly handles decimal places and uses appropriate rounding.


52-65: Verify the total change calculation logic

The portfolio change calculation involves multiple operations that could affect precision.

Let's verify the calculation logic:

✅ Verification successful

Portfolio change calculation is correctly implemented

The calculation logic in TotalChart.tsx is consistent with the implementation in useYouHave.ts. The calcChange function properly:

  • Handles edge cases (returns 0 when price change is -100%)
  • Calculates the change amount using the formula: (priceChange * balance * currentPrice) / 100
  • Uses proper decimal adjustment when converting balance: Number(balance) / (10 ** decimal)

The accumulation of total change through += is also appropriate as it aggregates changes across multiple assets in the portfolio.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other instances of calcChange usage to ensure consistency
rg -A 5 "calcChange\(" --type typescript

# Look for similar portfolio calculations in other components
ast-grep --pattern 'const totalChange = $_'

Length of output: 242


Script:

#!/bin/bash
# Let's search for calcChange function definition and its usages
rg "calcChange" -A 5

# Also search for price calculation related functions
rg "calcPrice" -A 5

# Look for the useYouHave hook implementation
fd "useYouHave" --exec cat {}

Length of output: 10088

packages/extension-polkagate/src/fullscreen/accountDetails/components/AccountInformationForDetails.tsx (2)

81-81: LGTM: Font size adjustment for better visual hierarchy.

The reduction in font size from 28px to 26px helps maintain proper visual hierarchy.


109-109: LGTM: Improved spacing between elements.

The added margin-left improves the visual spacing between the asset logo and balance information.

packages/extension-polkagate/src/fullscreen/homeFullScreen/partials/TotalBalancePieChart.tsx (3)

163-163: LGTM: Good refactor to use shared calcPrice function.

Moving the price calculation logic to a shared hook improves code reusability and maintainability.


235-238: LGTM: Improved decimal precision handling.

Good improvements in the CountUp component:

  1. Dynamic decimal places based on the actual value
  2. Consistent fallback to PORTFOLIO_CHANGE_DECIMAL
  3. Clean integration with changeSign utility

212-212: Verify layout behavior with height: 'fit-content'.

The change from minHeight to height: 'fit-content' might affect the component's resizing behavior. Please ensure this doesn't cause layout shifts when the content size changes (e.g., when toggling the "More" section).

✅ Verification successful

Using height: 'fit-content' is consistent with codebase patterns

The search results show that height: 'fit-content' is commonly used throughout the codebase, particularly in Grid components within the same application. This pattern appears in similar UI components like HomeMenu, WatchList, and other home screen partials, suggesting it's an established and tested approach for handling dynamic content in the application.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related layout styles or height properties
rg "height.*fit-content" --type tsx

Length of output: 65


Script:

#!/bin/bash
# Search for related layout styles or height properties with ripgrep
rg "height.*fit-content"

# Also search for similar Grid components with layout styles
ast-grep --pattern 'Grid $$$={$$$} sx={{ $$$height$$$, $$$}}'

Length of output: 10262

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.

2 participants