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: STAKE-824: [FE] build staking input confirmation screen #11605

Merged
merged 30 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6e253e0
fix: fixed broken redirect to stake in StakingButtons
Matt561 Sep 27, 2024
3fa0b64
fix: removed padding on tooltip modal
Matt561 Sep 27, 2024
8374020
feat: updated KeyValueRow tooltip to be question icon
Matt561 Sep 27, 2024
d31f3dc
feat: added StakeReviewView
Matt561 Oct 2, 2024
f724eeb
Merge remote-tracking branch 'origin/main' into feat/stake-824-build-…
Matt561 Oct 2, 2024
e5dfdf3
fix: updated tests after updating branch
Matt561 Oct 2, 2024
3761653
temp: added reminder todos
Matt561 Oct 2, 2024
b3e598c
fix: merged legalink navigation handlers into one
Matt561 Oct 2, 2024
b58d6f9
feat: connected stake confirmation screen to stake input
Matt561 Oct 2, 2024
101eca6
fix: fixed removed right-padding in staking cta
Matt561 Oct 3, 2024
d6b1eb6
feat: replaced hardcoded network name in AccountHeaderCard
Matt561 Oct 3, 2024
9cf0d94
feat: pass stake input params to stake confirmation screen
Matt561 Oct 3, 2024
23bbd7b
fix: updated tests
Matt561 Oct 3, 2024
a3d0563
fix: renamed StakeReview to StakeConfirmation
Matt561 Oct 3, 2024
7125724
Merge remote-tracking branch 'origin/main' into feat/stake-824-build-…
Matt561 Oct 3, 2024
749a4a6
fix: updated tests
Matt561 Oct 3, 2024
fb9392a
feat: added ContractTag component and updated stake confirmation inte…
Matt561 Oct 3, 2024
4b088a6
Merge remote-tracking branch 'origin/main' into feat/stake-824-build-…
Matt561 Oct 7, 2024
1413ba7
chore: fixed breaking changed from updating branch
Matt561 Oct 7, 2024
7f3ff6a
feat: changes based on PR review comments
Matt561 Oct 7, 2024
ab508c3
Merge branch 'main' into feat/stake-824-build-staking-input-confirmat…
Matt561 Oct 7, 2024
3c83673
feat: updated AmountHeader prop names
Matt561 Oct 8, 2024
3dcadce
Merge remote-tracking branch 'origin/main' into feat/stake-824-build-…
Matt561 Oct 8, 2024
213a766
feat: light refactor after updating branch
Matt561 Oct 8, 2024
5f1d773
Merge remote-tracking branch 'origin/main' into feat/stake-824-build-…
Matt561 Oct 15, 2024
793f6ca
feat: removed estimated gas card from StakeConfirmationView
Matt561 Oct 15, 2024
303a7ae
feat: updated test snapshot
Matt561 Oct 15, 2024
ea4211b
Merge branch 'main' into feat/stake-824-build-staking-input-confirmat…
Matt561 Oct 15, 2024
28a58d3
Merge branch 'main' into feat/stake-824-build-staking-input-confirmat…
Matt561 Oct 15, 2024
9379b1a
fix: renamed AmountHeader to TokenValueStack
Matt561 Oct 15, 2024
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
63 changes: 45 additions & 18 deletions app/components/UI/Navbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1824,34 +1824,61 @@ export const getSettingsNavigationOptions = (title, themeColors) => {
};
};

export function getStakingNavbar(title, navigation, themeColors) {
/**
*
* @param {String} title - Navbar Title.
* @param {NavigationProp<ParamListBase>} navigation Navigation object returned from useNavigation hook.
* @param {ThemeColors} themeColors theme.colors returned from useStyles hook.
* @param {{ backgroundColor?: string, hasCancelButton?: boolean, hasBackButton?: boolean }} [options] - Optional options for navbar.
* @returns Staking Navbar Component.
*/
export function getStakingNavbar(title, navigation, themeColors, options) {
const { hasBackButton = true, hasCancelButton = true } = options ?? {};

const innerStyles = StyleSheet.create({
headerStyle: {
backgroundColor:
options?.backgroundColor ?? themeColors.background.default,
shadowOffset: null,
},
headerLeft: {
marginHorizontal: 16,
},
headerButtonText: {
color: themeColors.primary.default,
fontSize: 14,
...fontStyles.normal,
},
headerStyle: {
backgroundColor: themeColors.background.default,
shadowColor: importedColors.transparent,
elevation: 0,
},
});

function navigationPop() {
navigation.goBack();
}

return {
headerTitle: () => (
<NavbarTitle title={title} disableNetwork translate={false} />
),
headerLeft: () => <View />,
headerRight: () => (
<TouchableOpacity
onPress={() => navigation.dangerouslyGetParent()?.pop()}
style={styles.closeButton}
>
<Text style={innerStyles.headerButtonText}>
{strings('navigation.cancel')}
</Text>
</TouchableOpacity>
<MorphText variant={TextVariant.HeadingMD}>{title}</MorphText>
),
headerStyle: innerStyles.headerStyle,
headerLeft: () =>
hasBackButton ? (
<ButtonIcon
size={ButtonIconSizes.Lg}
iconName={IconName.ArrowLeft}
onPress={navigationPop}
style={innerStyles.headerLeft}
/>
) : null,
headerRight: () =>
hasCancelButton ? (
<TouchableOpacity
onPress={() => navigation.dangerouslyGetParent()?.pop()}
style={styles.closeButton}
>
<Text style={innerStyles.headerButtonText}>
{strings('navigation.cancel')}
</Text>
</TouchableOpacity>
) : null,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Theme } from '../../../../../util/theme/models';
import { StyleSheet } from 'react-native';

const stylesSheet = (params: { theme: Theme }) => {
const { theme } = params;
const { colors } = theme;

return StyleSheet.create({
mainContainer: {
flex: 1,
paddingTop: 8,
Matt561 marked this conversation as resolved.
Show resolved Hide resolved
paddingHorizontal: 16,
backgroundColor: colors.background.alternative,
justifyContent: 'space-between',
},
cardsContainer: {
paddingTop: 16,
gap: 8,
},
});
};

export default stylesSheet;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import renderWithProvider from '../../../../../util/test/renderWithProvider';
import StakeConfirmationView from './StakeConfirmationView';
import { Image } from 'react-native';
import { createMockAccountsControllerState } from '../../../../../util/test/accountsControllerTestUtils';
import { backgroundState } from '../../../../../util/test/initial-root-state';
import configureMockStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import { StakeConfirmationViewProps } from './StakeConfirmationView.types';

jest.mock('../../../../hooks/useIpfsGateway', () => jest.fn());

Image.getSize = jest.fn((_uri, success) => {
success(100, 100); // Mock successful response for ETH native Icon Image
});

const MOCK_ADDRESS_1 = '0x0';
const MOCK_ADDRESS_2 = '0x1';

const MOCK_ACCOUNTS_CONTROLLER_STATE = createMockAccountsControllerState([
MOCK_ADDRESS_1,
MOCK_ADDRESS_2,
]);

const mockStore = configureMockStore();

const mockInitialState = {
settings: {},
engine: {
backgroundState: {
...backgroundState,
AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
};
const store = mockStore(mockInitialState);

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: jest
.fn()
.mockImplementation((callback) => callback(mockInitialState)),
}));

jest.mock('@react-navigation/native', () => {
const actualNav = jest.requireActual('@react-navigation/native');
return {
...actualNav,
useNavigation: () => ({
navigate: jest.fn(),
setOptions: jest.fn(),
}),
};
});

describe('StakeConfirmationView', () => {
it('render matches snapshot', () => {
const props: StakeConfirmationViewProps = {
route: {
key: '1',
params: { amountWei: '3210000000000000', amountFiat: '7.46' },
name: 'params',
},
};

const { toJSON } = renderWithProvider(
<Provider store={store}>
<StakeConfirmationView {...props} />
</Provider>,
);

expect(toJSON()).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useEffect } from 'react';
import { View } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { useStyles } from '../../../../hooks/useStyles';
import { getStakingNavbar } from '../../../Navbar';
import styleSheet from './StakeConfirmationView.styles';
import TokenValueStack from '../../components/StakingConfirmation/TokenValueStack/TokenValueStack';
import AccountHeaderCard from '../../components/StakingConfirmation/AccountHeaderCard/AccountHeaderCard';
import RewardsCard from '../../components/StakingConfirmation/RewardsCard/RewardsCard';
import ConfirmationFooter from '../../components/StakingConfirmation/ConfirmationFooter/ConfirmationFooter';
import { StakeConfirmationViewProps } from './StakeConfirmationView.types';
import { MOCK_GET_VAULT_RESPONSE } from '../../components/StakingBalance/mockData';
import { strings } from '../../../../../../locales/i18n';

const MOCK_REWARD_DATA = {
REWARDS: {
ETH: '0.13 ETH',
FIAT: '$334.93',
},
};
Matt561 marked this conversation as resolved.
Show resolved Hide resolved

const MOCK_STAKING_CONTRACT_NAME = 'MM Pooled Staking';

const StakeConfirmationView = ({ route }: StakeConfirmationViewProps) => {
const navigation = useNavigation();

const { styles, theme } = useStyles(styleSheet, {});

useEffect(() => {
navigation.setOptions(
getStakingNavbar(strings('stake.stake'), navigation, theme.colors, {
backgroundColor: theme.colors.background.alternative,
hasCancelButton: false,
}),
);
}, [navigation, theme.colors]);

return (
<View style={styles.mainContainer}>
<View>
<TokenValueStack
amountWei={route.params.amountWei}
amountFiat={`$${route.params.amountFiat}`}
tokenSymbol="ETH"
/>
<View style={styles.cardsContainer}>
<AccountHeaderCard contractName={MOCK_STAKING_CONTRACT_NAME} />
<RewardsCard
rewardRate={MOCK_GET_VAULT_RESPONSE.apy}
rewardsEth={MOCK_REWARD_DATA.REWARDS.ETH}
rewardsFiat={MOCK_REWARD_DATA.REWARDS.FIAT}
/>
</View>
</View>
<ConfirmationFooter />
</View>
);
};

export default StakeConfirmationView;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { RouteProp } from '@react-navigation/native';

interface StakeConfirmationViewRouteParams {
amountWei: string;
amountFiat: string;
}

export interface StakeConfirmationViewProps {
route: RouteProp<{ params: StakeConfirmationViewRouteParams }, 'params'>;
}
Loading
Loading