Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 10 additions & 45 deletions app/components/UI/Rewards/Views/OndoCampaignStatsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
import { useSelector } from 'react-redux';
import {
Box,
BoxAlignItems,
BoxFlexDirection,
FontWeight,
Icon,
IconColor,
IconName,
IconSize,
Skeleton,
Text,
TextColor,
TextVariant,
Expand All @@ -23,10 +21,9 @@ import HeaderCompactStandard from '../../../../component-library/components-temp
import ErrorBoundary from '../../../Views/ErrorBoundary';
import {
StatCell,
PendingTag,
IneligibleTag,
CAMPAIGN_STATS_SUMMARY_TEST_IDS,
} from '../components/Campaigns/CampaignStatsSummary';
import LeaderboardPositionHeader from '../components/Campaigns/LeaderboardPositionHeader';
import RewardsErrorBanner from '../components/RewardsErrorBanner';
import {
formatTierDisplayName,
Expand Down Expand Up @@ -217,47 +214,15 @@ const OndoCampaignStatsView: React.FC = () => {
showsVerticalScrollIndicator={false}
contentContainerStyle={tw.style('pb-4')}
>
<Box twClassName="p-4 gap-3">
{/* ── Top section: Your rank ── */}
<Box>
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
twClassName="gap-2"
>
<Text variant={TextVariant.HeadingMd}>
{strings('rewards.ondo_campaign_stats.label_your_rank')}
</Text>
{isIneligible && (
<IneligibleTag
testID={CAMPAIGN_STATS_SUMMARY_TEST_IDS.INELIGIBLE_TAG}
/>
)}
{!isIneligible && isPending && <PendingTag />}
{!isIneligible && isQualified && <CheckIcon />}
</Box>

{leaderboardLoading ? (
<Skeleton style={tw.style('h-9 w-28 rounded')} />
) : (
<Text
variant={TextVariant.DisplayLg}
fontWeight={FontWeight.Bold}
>
{rankValue}
</Text>
)}
</Box>

{/* Tier */}
<Box flexDirection={BoxFlexDirection.Row}>
<StatCell
label={strings('rewards.ondo_campaign_stats.label_tier')}
value={tierValue}
isLoading={leaderboardLoading}
/>
<Box twClassName="flex-1" />
</Box>
<Box twClassName="p-4">
<LeaderboardPositionHeader
rank={rankValue}
tier={tierValue}
isLoading={leaderboardLoading}
isPending={isPending}
isQualified={isQualified}
isIneligible={isIneligible}
/>
</Box>

{/* ── Divider ── */}
Expand Down
30 changes: 28 additions & 2 deletions app/components/UI/Rewards/Views/OndoLeaderboardView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import { useSelector } from 'react-redux';
import { useGetOndoLeaderboard } from '../hooks/useGetOndoLeaderboard';
import { useGetOndoLeaderboardPosition } from '../hooks/useGetOndoLeaderboardPosition';
import { useGetOndoPortfolioPosition } from '../hooks/useGetOndoPortfolioPosition';
import { useGetOndoCampaignDeposits } from '../hooks/useGetOndoCampaignDeposits';
import { useGetCampaignParticipantStatus } from '../hooks/useGetCampaignParticipantStatus';

const mockGoBack = jest.fn();
Expand Down Expand Up @@ -99,6 +101,8 @@

jest.mock('../hooks/useGetOndoLeaderboard');
jest.mock('../hooks/useGetOndoLeaderboardPosition');
jest.mock('../hooks/useGetOndoPortfolioPosition');
jest.mock('../hooks/useGetOndoCampaignDeposits');
jest.mock('../hooks/useGetCampaignParticipantStatus');

const mockUseGetOndoLeaderboard = useGetOndoLeaderboard as jest.MockedFunction<
Expand All @@ -108,6 +112,14 @@
useGetOndoLeaderboardPosition as jest.MockedFunction<
typeof useGetOndoLeaderboardPosition
>;
const mockUseGetOndoPortfolioPosition =
useGetOndoPortfolioPosition as jest.MockedFunction<
typeof useGetOndoPortfolioPosition
>;
const mockUseGetOndoCampaignDeposits =
useGetOndoCampaignDeposits as jest.MockedFunction<
typeof useGetOndoCampaignDeposits
>;
const mockUseGetCampaignParticipantStatus =
useGetCampaignParticipantStatus as jest.MockedFunction<
typeof useGetCampaignParticipantStatus
Expand Down Expand Up @@ -179,6 +191,18 @@
});
mockUseGetOndoLeaderboard.mockReturnValue(hookDefaults);
mockUseGetOndoLeaderboardPosition.mockReturnValue(positionDefaults);
mockUseGetOndoPortfolioPosition.mockReturnValue({

Check failure on line 194 in app/components/UI/Rewards/Views/OndoLeaderboardView.test.tsx

View workflow job for this annotation

GitHub Actions / Run `lint:tsc`

Argument of type '{ portfolio: null; isLoading: false; hasError: false; refetch: jest.Mock<any, any, any>; }' is not assignable to parameter of type 'UseGetOndoPortfolioPositionResult'.
portfolio: null,
isLoading: false,
hasError: false,
refetch: jest.fn(),
});
mockUseGetOndoCampaignDeposits.mockReturnValue({
deposits: null,
isLoading: false,
hasError: false,
refetch: jest.fn(),
});
});

it('renders with the correct container testID', () => {
Expand Down Expand Up @@ -209,8 +233,10 @@
},
});
const { getByText } = render(<OndoLeaderboardView />);
expect(getByText('Rank')).toBeDefined();
expect(getByText('Tier')).toBeDefined();
expect(
getByText('rewards.ondo_campaign_stats.label_your_rank'),
).toBeDefined();
expect(getByText('rewards.ondo_campaign_stats.label_tier')).toBeDefined();
Comment thread
sophieqgu marked this conversation as resolved.
});

it('calls useGetOndoLeaderboard with the campaign ID from route params', () => {
Expand Down
71 changes: 46 additions & 25 deletions app/components/UI/Rewards/Views/OndoLeaderboardView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { ScrollView } from 'react-native';
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
import {
Box,
BoxFlexDirection,
Text,
TextColor,
TextVariant,
} from '@metamask/design-system-react-native';
import { useTailwind } from '@metamask/design-system-twrnc-preset';
Expand All @@ -13,17 +13,15 @@ import { useSelector } from 'react-redux';
import HeaderCompactStandard from '../../../../component-library/components-temp/HeaderCompactStandard';
import ErrorBoundary from '../../../Views/ErrorBoundary';
import OndoLeaderboard from '../components/Campaigns/OndoLeaderboard';
import {
StatCell,
PendingTag,
} from '../components/Campaigns/CampaignStatsSummary';
import {
formatTierDisplayName,
getTierMinNetDeposit,
} from '../components/Campaigns/OndoLeaderboard.utils';
import LeaderboardPositionHeader from '../components/Campaigns/LeaderboardPositionHeader';
import { formatTierDisplayName } from '../components/Campaigns/OndoLeaderboard.utils';
import { useGetOndoLeaderboard } from '../hooks/useGetOndoLeaderboard';
import { useGetOndoLeaderboardPosition } from '../hooks/useGetOndoLeaderboardPosition';
import { useGetOndoPortfolioPosition } from '../hooks/useGetOndoPortfolioPosition';
import { useGetOndoCampaignDeposits } from '../hooks/useGetOndoCampaignDeposits';
import { useGetCampaignParticipantStatus } from '../hooks/useGetCampaignParticipantStatus';
import { getCurrentPrize } from '../components/Campaigns/OndoPrizePool';
import { formatPercentChange, formatUsd } from '../utils/formatUtils';
import { strings } from '../../../../../locales/i18n';
import Routes from '../../../../constants/navigation/Routes';
import {
Expand Down Expand Up @@ -68,7 +66,29 @@ const OndoLeaderboardView: React.FC = () => {
const { position, isLoading: isPositionLoading } =
useGetOndoLeaderboardPosition(isOptedIn ? campaignId : undefined);

const { portfolio: portfolioData, isLoading: isPortfolioLoading } =
useGetOndoPortfolioPosition(isOptedIn ? campaignId : undefined);

const { deposits, isLoading: isDepositsLoading } =
useGetOndoCampaignDeposits(campaignId);

const isPending = position != null && !position.qualified;
const isQualified = position != null && position.qualified;

const returnValue = portfolioData?.summary
? formatPercentChange(portfolioData.summary.portfolioPnlPercent)
: undefined;

const returnColor = portfolioData?.summary
? parseFloat(portfolioData.summary.portfolioPnlPercent) < 0
? TextColor.ErrorDefault
: TextColor.SuccessDefault
: TextColor.TextDefault;

const prizePoolValue = deposits?.totalUsdDeposited
? formatUsd(getCurrentPrize(parseFloat(deposits.totalUsdDeposited)))
: undefined;

const {
leaderboard: leaderboardData,
selectedTier,
Expand Down Expand Up @@ -116,25 +136,26 @@ const OndoLeaderboardView: React.FC = () => {
>
{/* User position */}
{position && (
<Box twClassName="p-4 gap-3">
<Box flexDirection={BoxFlexDirection.Row}>
<StatCell
label="Rank"
value={String(position.rank).padStart(2, '0')}
isLoading={isPositionLoading}
suffix={isPending ? <PendingTag /> : undefined}
/>
<StatCell
label="Tier"
value={formatTierDisplayName(position.projectedTier)}
isLoading={isPositionLoading}
/>
</Box>
<Box twClassName="p-4">
<LeaderboardPositionHeader
rank={String(position.rank).padStart(2, '0')}
tier={formatTierDisplayName(position.projectedTier)}
isLoading={isPositionLoading}
isPending={isPending}
isQualified={isQualified}
showReturn
returnValue={returnValue}
returnColor={returnColor}
showPrizePool
prizePoolValue={prizePoolValue}
prizePoolLoading={isDepositsLoading && !deposits}
/>
</Box>
)}

{/* ── Divider ── */}
<Box twClassName="my-1 border-b border-border-muted" />
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated
{/* Full leaderboard */}
<Box>
<Box twClassName="py-4">
<OndoLeaderboard
tierNames={tierNames}
selectedTier={selectedTier}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,31 @@ export const StatCell: React.FC<StatCellProps> = ({
const tw = useTailwind();
return (
<Box style={CELL_STYLE} twClassName="gap-0.5">
<Text
variant={TextVariant.BodySm}
fontWeight={FontWeight.Medium}
color={TextColor.TextAlternative}
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
twClassName="gap-1.5"
>
{label}
</Text>
<Text
variant={TextVariant.BodySm}
fontWeight={FontWeight.Medium}
color={TextColor.TextAlternative}
>
{label}
</Text>
{!isLoading && suffix}
</Box>
{isLoading ? (
<Skeleton style={tw.style('h-5 w-20 rounded')} />
) : (
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
twClassName="gap-2"
<Text
variant={TextVariant.BodyMd}
fontWeight={FontWeight.Medium}
color={valueColor}
testID={testID}
>
<Text
variant={TextVariant.BodyMd}
fontWeight={FontWeight.Medium}
color={valueColor}
testID={testID}
>
{value}
</Text>
{suffix}
</Box>
{value}
</Text>
)}
</Box>
);
Expand Down
Loading
Loading