-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create initial portfolio screen (#15)
* Rename header * Extract BalanceAndActions component; use it in PortfolioScreen * Create store/type/factory for balances * Create balance UI in portfolio screen * Use more precise naming * Tweak factories * Wrap Storybook stories in <ReduxProvider /> * Fix ATOM mock data * Delete BalanceList stories for now * Build a simple AssetActionSheet * Add comment
- Loading branch information
1 parent
35f28b0
commit 3f1bc64
Showing
20 changed files
with
396 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Trans } from '@lingui/react/macro'; | ||
import { Sx, Text, View } from 'dripsy'; | ||
import Button from '../Button'; | ||
import { useAppDispatch, useAppSelector } from '@/store/hooks'; | ||
import { close, open } from '@/store/depositFlow'; | ||
import DepositFlow from '../DepositFlow'; | ||
|
||
/** | ||
* Renders the user's current balance, as well as buttons for actions related to | ||
* their balance (such as Send/Deposit/Request). | ||
*/ | ||
export default function BalanceAndActions() { | ||
const dispatch = useAppDispatch(); | ||
const isOpen = useAppSelector(state => state.depositFlow.isOpen); | ||
|
||
return ( | ||
<> | ||
<View sx={sx.root}> | ||
<View sx={sx.balanceWrapper}> | ||
<Text sx={sx.balanceLabel}> | ||
<Trans>Balance</Trans> | ||
</Text> | ||
<Text sx={sx.balance}>0.00 USDC</Text> | ||
</View> | ||
|
||
<View sx={sx.buttons}> | ||
<Button actionType='accent' onPress={() => dispatch(open())}> | ||
<Trans>Deposit</Trans> | ||
</Button> | ||
<Button> | ||
<Trans>Request</Trans> | ||
</Button> | ||
</View> | ||
</View> | ||
|
||
<DepositFlow isOpen={isOpen} onClose={() => dispatch(close())} /> | ||
</> | ||
); | ||
} | ||
|
||
const sx = { | ||
balance: { | ||
variant: 'text.h4', | ||
}, | ||
|
||
balanceLabel: { | ||
variant: 'text.small', | ||
|
||
color: 'neutralLight', | ||
}, | ||
|
||
balanceWrapper: { | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
flexGrow: 1, | ||
}, | ||
|
||
buttons: { | ||
flexDirection: 'row', | ||
flexGrow: 0, | ||
gap: '$2', | ||
px: '$4', | ||
pb: '$4', | ||
}, | ||
|
||
root: { | ||
flexGrow: 1, | ||
flexDirection: 'column', | ||
}, | ||
} satisfies Record<string, Sx>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,21 @@ | ||
import Button from '../Button'; | ||
import { Sx, Text, View } from 'dripsy'; | ||
import DepositFlow from '../DepositFlow'; | ||
import { useAppDispatch, useAppSelector } from '@/store/hooks'; | ||
import { close, open } from '@/store/depositFlow'; | ||
import { Trans } from '@lingui/react/macro'; | ||
import { Sx, View } from 'dripsy'; | ||
import HomeScreenTransactionsList from './HomeScreenTransactionsList'; | ||
import BalanceAndActions from '../BalanceAndActions'; | ||
|
||
export default function HomeScreen() { | ||
const dispatch = useAppDispatch(); | ||
const isOpen = useAppSelector(state => state.depositFlow.isOpen); | ||
|
||
return ( | ||
<> | ||
<View sx={sx.root}> | ||
{/** @todo: Make this a `ScrollView`. */} | ||
<View sx={sx.root}> | ||
<View sx={sx.balanceWrapper}> | ||
<Text sx={sx.balanceLabel}> | ||
<Trans>Balance</Trans> | ||
</Text> | ||
<Text sx={sx.balance}>0.00 USDC</Text> | ||
</View> | ||
|
||
<View sx={sx.buttons}> | ||
<Button actionType='accent' onPress={() => dispatch(open())}> | ||
<Trans>Deposit</Trans> | ||
</Button> | ||
<Button> | ||
<Trans>Request</Trans> | ||
</Button> | ||
</View> | ||
<BalanceAndActions /> | ||
|
||
<HomeScreenTransactionsList /> | ||
</View> | ||
|
||
<DepositFlow isOpen={isOpen} onClose={() => dispatch(close())} /> | ||
</> | ||
<HomeScreenTransactionsList /> | ||
</View> | ||
); | ||
} | ||
|
||
const sx = { | ||
balance: { | ||
variant: 'text.h4', | ||
}, | ||
|
||
balanceLabel: { | ||
variant: 'text.small', | ||
|
||
color: 'neutralLight', | ||
}, | ||
|
||
balanceWrapper: { | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
flexGrow: 1, | ||
}, | ||
|
||
buttons: { | ||
flexDirection: 'row', | ||
flexGrow: 0, | ||
gap: '$2', | ||
px: '$4', | ||
pb: '$4', | ||
}, | ||
|
||
root: { | ||
flexGrow: 1, | ||
flexDirection: 'column', | ||
px: 'screenHorizontalMargin', | ||
}, | ||
} satisfies Record<string, Sx>; |
69 changes: 69 additions & 0 deletions
69
react-native-expo/components/PortfolioScreen/BalanceList/AssetActionSheet/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import ActionSheet from '@/components/ActionSheet'; | ||
import AssetIcon from '@/components/AssetIcon'; | ||
import TransactionList from '@/components/TransactionList'; | ||
import { useAppDispatch, useAppSelector } from '@/store/hooks'; | ||
import { setSelectedAssetSymbol } from '@/store/portfolioScreen'; | ||
import { Sx, Text, View } from 'dripsy'; | ||
import useTransactionsForAsset from './useTransactionsForAsset'; | ||
|
||
/** | ||
* An action sheet for a given asset, with a list of relevant transactions and | ||
* buttons for actions related to the asset (such as sending). | ||
*/ | ||
export default function AssetActionSheet() { | ||
const selectedAssetSymbol = useAppSelector(state => state.portfolioScreen.selectedAssetSymbol); | ||
const balance = useAppSelector(state => | ||
state.balances.balances.find(balance => balance.assetSymbol === selectedAssetSymbol), | ||
); | ||
const dispatch = useAppDispatch(); | ||
const transactions = useTransactionsForAsset(selectedAssetSymbol); | ||
|
||
return ( | ||
<ActionSheet | ||
isOpen={!!selectedAssetSymbol} | ||
onClose={() => dispatch(setSelectedAssetSymbol(undefined))} | ||
> | ||
<View sx={sx.header}> | ||
<View sx={sx.assetIconWrapper}> | ||
<AssetIcon /> | ||
</View> | ||
|
||
<Text sx={sx.balance}> | ||
{balance?.amount} {balance?.assetSymbol} | ||
</Text> | ||
|
||
<Text sx={sx.equivalentValue}>{balance?.equivalentValue} USDC</Text> | ||
</View> | ||
|
||
<TransactionList transactions={transactions} showTitle /> | ||
</ActionSheet> | ||
); | ||
} | ||
|
||
const sx = { | ||
assetIconWrapper: { | ||
pb: '$2', | ||
}, | ||
|
||
balance: { | ||
variant: 'text.h4', | ||
|
||
textAlign: 'center', | ||
}, | ||
|
||
equivalentValue: { | ||
variant: 'text.small', | ||
|
||
color: 'neutralLight', | ||
textAlign: 'center', | ||
}, | ||
|
||
header: { | ||
flexDirection: 'column', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
flexGrow: 1, | ||
gap: '$1', | ||
mb: '$4', | ||
}, | ||
} satisfies Record<string, Sx>; |
20 changes: 20 additions & 0 deletions
20
...e-expo/components/PortfolioScreen/BalanceList/AssetActionSheet/useTransactionsForAsset.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { useAppSelector } from '@/store/hooks'; | ||
import { useMemo } from 'react'; | ||
|
||
/** Returns a memoized array of the transactions for a given asset. */ | ||
export default function useTransactionsForAsset( | ||
/** The symbol of the asset that transactions should be filtered by. */ | ||
assetSymbol?: string, | ||
) { | ||
const transactions = useAppSelector(state => state.transactions.transactions); | ||
|
||
const transactionsForAsset = useMemo( | ||
() => | ||
assetSymbol | ||
? transactions.filter(transaction => transaction.assetSymbol === assetSymbol) | ||
: [], | ||
[transactions, assetSymbol], | ||
); | ||
|
||
return transactionsForAsset; | ||
} |
20 changes: 20 additions & 0 deletions
20
react-native-expo/components/PortfolioScreen/BalanceList/Balance/index.stories.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import Balance from '.'; | ||
import balanceFactory from '@/factories/balance'; | ||
|
||
const meta: Meta<typeof Balance> = { | ||
component: Balance, | ||
tags: ['autodocs'], | ||
argTypes: { | ||
balance: { control: false }, | ||
}, | ||
}; | ||
|
||
export default meta; | ||
|
||
export const Basic: StoryObj<typeof Balance> = { | ||
args: { | ||
balance: balanceFactory.build(), | ||
}, | ||
}; |
41 changes: 41 additions & 0 deletions
41
react-native-expo/components/PortfolioScreen/BalanceList/Balance/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import AssetIcon from '@/components/AssetIcon'; | ||
import ListItem from '@/components/ListItem'; | ||
import { useAppDispatch } from '@/store/hooks'; | ||
import { setSelectedAssetSymbol } from '@/store/portfolioScreen'; | ||
import IBalance from '@/types/Balance'; | ||
import { Sx, Text, View } from 'dripsy'; | ||
|
||
export interface BalanceProps { | ||
balance: IBalance; | ||
} | ||
|
||
export default function Balance({ balance }: BalanceProps) { | ||
const dispatch = useAppDispatch(); | ||
|
||
return ( | ||
<ListItem | ||
avatar={<AssetIcon />} | ||
primaryText={balance.assetSymbol} | ||
secondaryText={balance.assetName} | ||
suffix={ | ||
<View sx={sx.suffix}> | ||
<Text variant='small'>{balance.amount}</Text> | ||
<Text sx={sx.equivalentValue}>{balance.equivalentValue} USDC</Text> | ||
</View> | ||
} | ||
onPress={() => dispatch(setSelectedAssetSymbol(balance.assetSymbol))} | ||
/> | ||
); | ||
} | ||
|
||
const sx = { | ||
equivalentValue: { | ||
variant: 'text.detail', | ||
color: 'neutralLight', | ||
}, | ||
|
||
suffix: { | ||
flexDirection: 'column', | ||
alignItems: 'flex-end', | ||
}, | ||
} satisfies Record<string, Sx>; |
26 changes: 26 additions & 0 deletions
26
react-native-expo/components/PortfolioScreen/BalanceList/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import List from '@/components/List'; | ||
import IBalance from '@/types/Balance'; | ||
import { useLingui } from '@lingui/react/macro'; | ||
import Balance from './Balance'; | ||
import AssetActionSheet from './AssetActionSheet'; | ||
|
||
export interface BalanceListProps { | ||
balances: IBalance[]; | ||
} | ||
|
||
/** Shows a list of the user's balances in every asset they hold. */ | ||
export default function BalanceList({ balances }: BalanceListProps) { | ||
const { t } = useLingui(); | ||
|
||
return ( | ||
<> | ||
<List title={t`Assets`}> | ||
{balances.map(balance => ( | ||
<Balance key={balance.assetSymbol} balance={balance} /> | ||
))} | ||
</List> | ||
|
||
<AssetActionSheet /> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,24 @@ | ||
import { Text } from 'dripsy'; | ||
import { Sx, View } from 'dripsy'; | ||
import BalanceAndActions from '../BalanceAndActions'; | ||
import BalanceList from './BalanceList'; | ||
import { useAppSelector } from '@/store/hooks'; | ||
|
||
export default function PortfolioScreen() { | ||
return <Text>PortfolioScreen</Text>; | ||
const balances = useAppSelector(state => state.balances.balances); | ||
|
||
return ( | ||
<View sx={sx.root}> | ||
{/** @todo: Make this a `ScrollView`. */} | ||
<BalanceAndActions /> | ||
|
||
<BalanceList balances={balances} /> | ||
</View> | ||
); | ||
} | ||
|
||
const sx = { | ||
root: { | ||
flexGrow: 1, | ||
px: 'screenHorizontalMargin', | ||
}, | ||
} satisfies Record<string, Sx>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes
Oops, something went wrong.