Skip to content

Commit

Permalink
borrow loan token - add static UI (#1293)
Browse files Browse the repository at this point in the history
* feat: add search input component

* refactor: onpress props for loancards

* wip: add choose loan token screen

* feat: add confirm screen static UI

Add navigation to borrow loan token screen

* wip: placeholder screen for borrow loan token

* wip: add loan token input UI

* config: add color for vault status tag

* feat: refactor VaultStatusTag and update to new UI

* wip: placeholder for BottomSheetVaultList

* config: add tailwind color

* feat: add bottom sheet vault list

that retrieves only non liquidated vault

* feat: add borrow loan token screen

Add loan token input

Add vault input

Add transaction details section

Add continue button validation logic

Add loan amount input

* feat: remove vault status temporarily

* feat: add hook to get col ratio text color

* test: update vault status used in loan card test

* feat(ui): optimize loan input for long number

* feat: replace with loan tokens from api

* revert: darkblue color from tailwind

It will be added from PR #1274

* feat: update threshold value for collateralization ratio

* fix: lint error

* feat: add placeholder to loan amount input

* feat: show clear input button only on non-empty string

* fix: list in bottom nav screen not scrollable

By replacing with BottomSheetFlatList

* revert: blue tailwind color

Will be added in PR #1274

* revert: style.json from tailwind-rn

* test: update snapshot

* added blue color

* added blue color

Co-authored-by: thedoublejay <[email protected]>
  • Loading branch information
kyleleow and thedoublejay authored Nov 16, 2021
1 parent 0f9fbe1 commit f7fdf85
Show file tree
Hide file tree
Showing 25 changed files with 2,693 additions and 1,247 deletions.
28 changes: 25 additions & 3 deletions mobile-app/app/components/BottomSheetTokenList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { Platform, TouchableOpacity, View } from 'react-native'
import NumberFormat from 'react-number-format'
import BigNumber from 'bignumber.js'
import { SymbolIcon } from './SymbolIcon'
import { ThemedFlatList, ThemedIcon, ThemedText, ThemedTouchableOpacity, ThemedView } from './themed'
import { ThemedIcon, ThemedText, ThemedTouchableOpacity, ThemedView } from './themed'
import { NavigationProp, useNavigation } from '@react-navigation/native'
import { BottomSheetWithNavRouteParam } from './BottomSheetWithNav'
import { BottomSheetFlatList } from '@gorhom/bottom-sheet'
import { useThemeContext } from '@shared-contexts/ThemeProvider'

interface BottomSheetTokenListProps {
headerLabel: string
Expand All @@ -31,6 +33,7 @@ export const BottomSheetTokenList = ({
onTokenPress,
navigateToScreen
}: BottomSheetTokenListProps): React.MemoExoticComponent<() => JSX.Element> => memo(() => {
const { isLight } = useThemeContext()
const navigation = useNavigation<NavigationProp<BottomSheetWithNavRouteParam>>()
const tokenList: BottomSheetToken[] = [
{
Expand Down Expand Up @@ -62,11 +65,29 @@ export const BottomSheetTokenList = ({
name: 'DFI',
available: new BigNumber('123'),
collateralFactor: new BigNumber(100)
},
{
id: 'dBCH1',
name: 'DFI',
available: new BigNumber('123'),
collateralFactor: new BigNumber(100)
},
{
id: 'dBCH2',
name: 'DFI',
available: new BigNumber('123'),
collateralFactor: new BigNumber(100)
},
{
id: 'dBCH3',
name: 'DFI',
available: new BigNumber('123'),
collateralFactor: new BigNumber(100)
}
]

return (
<ThemedFlatList
<BottomSheetFlatList
data={tokenList}
renderItem={({ item }): JSX.Element => (
<ThemedTouchableOpacity
Expand Down Expand Up @@ -125,7 +146,7 @@ export const BottomSheetTokenList = ({
<ThemedView
light={tailwind('bg-white border-gray-200')}
dark={tailwind('bg-gray-800 border-gray-700')}
style={tailwind('flex flex-row justify-between items-center px-4 py-2 border-b', { 'h-14 mt-px': Platform.OS === 'android' })}
style={tailwind('flex flex-row justify-between items-center px-4 py-2 border-b', { 'py-3.5 border-t -mb-px': Platform.OS === 'android' })} // border top on android to handle 1px of horizontal transparent line when scroll past header
>
<ThemedText
style={tailwind('text-lg font-medium')}
Expand All @@ -139,6 +160,7 @@ export const BottomSheetTokenList = ({
}
stickyHeaderIndices={[0]}
keyExtractor={(item) => item.id}
style={tailwind({ 'bg-gray-800': !isLight, 'bg-white': isLight })}
/>
)
})
1 change: 1 addition & 0 deletions mobile-app/app/components/BottomSheetWithNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const BottomSheetWithNav = React.memo((props: BottomSheetWithNavProps): J
ref={props.modalRef}
index={0}
snapPoints={getSnapPoints()}
enablePanDownToClose={false}
backdropComponent={(backdropProps: BottomSheetBackdropProps) => (
<View {...backdropProps} style={[backdropProps.style, tailwind('bg-black bg-opacity-60')]} />
)}
Expand Down
49 changes: 49 additions & 0 deletions mobile-app/app/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ThemedIcon, ThemedTextInput, ThemedView } from '@components/themed'
import { ClearButton } from '@components/WalletTextInput'
import { tailwind } from '@tailwind'
import React from 'react'
import { TextInputProps } from 'react-native'

type SearchInputProps = React.PropsWithChildren<TextInputProps> & ISearchInputProps

interface ISearchInputProps {
showClearButton: boolean
onClearInput: () => void
}

export function SearchInput (props: SearchInputProps): JSX.Element {
const {
onClearInput,
...otherProps
} = props
return (
<ThemedView
light={tailwind('bg-gray-100')}
dark={tailwind('bg-gray-900')}
style={tailwind('rounded-lg flex flex-row items-center py-1 pl-2 flex-1')}
>
<ThemedIcon
iconType='MaterialIcons'
name='search'
size={16}
light={tailwind('text-gray-600')}
dark={tailwind('text-gray-300')}
style={tailwind('mr-2')}
/>
<ThemedTextInput
{...otherProps}
style={tailwind('flex-grow w-8/12 h-8')}
/>
{props.showClearButton &&
(
<ClearButton
onPress={onClearInput}
iconThemedProps={{
light: tailwind('text-gray-300'),
dark: tailwind('text-gray-600')
}}
/>
)}
</ThemedView>
)
}
5 changes: 3 additions & 2 deletions mobile-app/app/components/WalletTextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { forwardRef, useState } from 'react'
import { Platform, TextInputProps } from 'react-native'
import { ThemedView, ThemedText, ThemedTextInput, ThemedIcon, ThemedSectionTitle, ThemedTouchableOpacity } from '@components/themed'
import { ThemedView, ThemedText, ThemedTextInput, ThemedIcon, ThemedSectionTitle, ThemedTouchableOpacity, ThemedProps } from '@components/themed'
import { tailwind } from '@tailwind'

type WalletTextInputProps = React.PropsWithChildren<TextInputProps> & IWalletTextInputProps
Expand Down Expand Up @@ -120,7 +120,7 @@ export const WalletTextInput = forwardRef<any, WalletTextInputProps>(function (p
)
})

function ClearButton (props: {onPress?: () => void, testID?: string}): JSX.Element {
export function ClearButton (props: {onPress?: () => void, testID?: string, iconThemedProps?: ThemedProps}): JSX.Element {
return (
<ThemedTouchableOpacity
testID={props.testID}
Expand All @@ -140,6 +140,7 @@ function ClearButton (props: {onPress?: () => void, testID?: string}): JSX.Eleme
size={28}
light={tailwind('text-gray-100')}
dark={tailwind('text-gray-700')}
{...props.iconThemedProps}
/>

</ThemedTouchableOpacity>
Expand Down
27 changes: 27 additions & 0 deletions mobile-app/app/hooks/wallet/CollateralizationRatioColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ThemedProps } from '@components/themed'
import BigNumber from 'bignumber.js'
import { tailwind } from '@tailwind'

interface UseCollateralizationRatioColorProps {
value: string
minColRatio: string
}

export function UseCollateralizationRatioColor (props: UseCollateralizationRatioColorProps): ThemedProps {
const collateralizationRatio = new BigNumber(props.value)
const style: ThemedProps = {}
const atRiskThreshold = new BigNumber(props.minColRatio).multipliedBy(1.5)
const liquidatedThreshold = new BigNumber(props.minColRatio).multipliedBy(1.25)

if (collateralizationRatio.isLessThan(liquidatedThreshold)) {
style.light = tailwind('text-error-500')
style.dark = tailwind('text-darkerror-500')
} else if (collateralizationRatio.isLessThan(atRiskThreshold)) {
style.light = tailwind('text-warning-500')
style.dark = tailwind('text-darkwarning-500')
} else {
style.light = tailwind('text-success-500')
style.dark = tailwind('text-darksuccess-500')
}
return style
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createStackNavigator } from '@react-navigation/stack'
import * as React from 'react'
import { HeaderFont } from '@components/Text'
import { HeaderTitle } from '@components/HeaderTitle'
import { LoanScheme } from '@defichain/whale-api-client/dist/api/loan'
import { LoanScheme, LoanToken, LoanVaultActive } from '@defichain/whale-api-client/dist/api/loan'
import { translate } from '@translations'
import { NetworkDetails } from '../Settings/screens/NetworkDetails'
import { LoadingState, LoansScreen } from './LoansScreen'
Expand All @@ -12,6 +12,9 @@ import BigNumber from 'bignumber.js'
import { VaultDetailScreen } from './VaultDetail/VaultDetailScreen'
import { AddCollateralScreen, Collateral } from './screens/AddCollateralScreen'
import { ConfirmAddCollateralScreen } from './screens/ConfirmAddCollateralScreen'
import { ChooseLoanTokenScreen } from './screens/ChooseLoanTokenScreen'
import { BorrowLoanTokenScreen } from './screens/BorrowLoanTokenScreen'
import { ConfirmBorrowLoanTokenScreen } from './screens/ConfirmBorrowLoanTokenScreen'
import { ConversionParam } from '@screens/AppNavigator/screens/Balances/BalancesNavigator'
import { TouchableOpacity } from 'react-native'
import { ThemedIcon } from '@components/themed'
Expand Down Expand Up @@ -43,7 +46,14 @@ export interface LoanParamList {
totalCollateralValue: BigNumber
fee: BigNumber
}

BorrowLoanTokenScreen: {
loanToken: LoanToken
vault?: LoanVaultActive
}
ConfirmBorrowLoanTokenScreen: {
loanToken: LoanToken
vault: LoanVaultActive
}
[key: string]: undefined | object
}

Expand Down Expand Up @@ -158,6 +168,42 @@ export function LoansNavigator (): JSX.Element {
)
}}
/>
<LoansStack.Screen
component={ChooseLoanTokenScreen}
name='ChooseLoanTokenScreen'
options={{
headerBackTitleVisible: false,
headerTitle: () => (
<HeaderTitle
text={translate('screens/LoansScreen', 'Choose Loan Token to Borrow') + ' (Beta)'} // TODO: remove beta from title
/>
)
}}
/>
<LoansStack.Screen
component={BorrowLoanTokenScreen}
name='BorrowLoanTokenScreen'
options={{
headerBackTitleVisible: false,
headerTitle: () => (
<HeaderTitle
text={translate('screens/LoansScreen', 'Borrow Loan Token') + ' (Beta)'} // TODO: remove beta from title
/>
)
}}
/>
<LoansStack.Screen
component={ConfirmBorrowLoanTokenScreen}
name='ConfirmBorrowLoanTokenScreen'
options={{
headerBackTitleVisible: false,
headerTitle: () => (
<HeaderTitle
text={translate('screens/LoansScreen', 'Confirm Borrow Loan Token') + ' (Beta)'} // TODO: remove beta from title
/>
)
}}
/>
</LoansStack.Navigator>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react'
import { View } from 'react-native'
import { tailwind } from '@tailwind'
import { ThemedView } from '@components/themed'
import { LoanCards } from '@components/LoanCards'
import { Tabs } from '@components/Tabs'
import { Vaults } from './components/Vaults'
import { EmptyVault } from './components/EmptyVault'
Expand All @@ -12,6 +11,7 @@ import { RootState } from '@store'
import { fetchLoanTokens, fetchVaults } from '@store/loans'
import { useWhaleApiClient } from '@shared-contexts/WhaleContext'
import { useWalletContext } from '@shared-contexts/WalletContext'
import { LoanCards } from './components/LoanCards'

enum TabKey {
BrowseLoans = 'BROWSE_LOANS',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { View } from '@components'
import { ThemedIcon, ThemedProps, ThemedScrollView, ThemedText, ThemedView } from '@components/themed'
import { Collateral, VaultCardProps, VaultStatus } from '@screens/AppNavigator/screens/Loans/components/VaultCard'
import { Collateral, VaultCardProps } from '@screens/AppNavigator/screens/Loans/components/VaultCard'
import { StackScreenProps } from '@react-navigation/stack'
import { tailwind } from '@tailwind'
import { translate } from '@translations'
Expand All @@ -25,7 +25,6 @@ export function VaultDetailScreen ({ route, navigation }: Props): JSX.Element {

const currentVault: VaultCardProps = {
vaultAddress: '22ffasd5ca123123123123123121231061',
status: VaultStatus.AtRisk,
collaterals: [
{ id: 'BTC', vaultProportion: new BigNumber(20) },
{ id: 'DFI', vaultProportion: new BigNumber(12.4573) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,7 @@ export function EmptyActiveLoans (): JSX.Element {
<Button
label={translate('components/EmptyActiveLoans', 'BROWSE LOANS')}
onPress={() => {
// TODO: replace navigation to browse loans tab in loans screen
navigation.navigate({
name: 'VaultDetailScreen',
params: {
vaultId: '22ffasd5ca123123123123123121231061',
emptyActiveLoans: false
},
merge: true
})
navigation.navigate('ChooseLoanTokenScreen')
}}
testID='button_browse_loans'
title='Browse loans'
Expand Down
Loading

0 comments on commit f7fdf85

Please sign in to comment.