Last active
August 26, 2022 08:36
-
-
Save emmacv/52083b0c70224baecfcd8197ed49c6df to your computer and use it in GitHub Desktop.
Gist to demonstrate the behaviour this component render.
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
// hook | |
import { useDebugValue, useEffect, useState } from 'react'; | |
import { useUserListAccountMovementsInfinite } from '@api/account-movements/account-movements'; | |
import { AccountMovements } from '@api/fRQTALNFTsAPI.schemas'; | |
import i18n from '@helpers/i18n'; | |
import SETTINGS from '../../shared/constants/transactionOptions'; | |
type Transactions = Record<string, (AccountMovements | undefined)[]>; | |
const CURRENT_MONTH_INDEX = new Date().getMonth(); | |
const ALL_TRANSACTIONS_KEY = i18n.t('wallet.allTransactions'); | |
const MONTHS = (() => { | |
const months = Array.from({ length: 12 }, (_, i) => | |
new Date(2000, i, 1).toLocaleString('default', { | |
month: 'long', | |
}), | |
); | |
return months; | |
})(); | |
const getNextPageParam = (lastPage, pages) => | |
lastPage?.data.length ? pages.length + 1 : undefined; | |
const useTransactions = (orderBy: keyof typeof SETTINGS) => { | |
const [transactions, setTransactions] = useState<Transactions>({ [ALL_TRANSACTIONS_KEY]: [] }); | |
const { data, ...query } = useUserListAccountMovementsInfinite(undefined, { | |
query: { | |
getNextPageParam, | |
}, | |
}); | |
useDebugValue(`order by: ${orderBy}`); | |
const transform = (transactionsList: AccountMovements[]) => { | |
const result = transactionsList?.reduce<Transactions>((current, transaction) => { | |
const monthIndex = new Date(transaction.transaction_date).getMonth(); | |
const month = | |
monthIndex === CURRENT_MONTH_INDEX ? i18n.t('wallet.thisMonth') : MONTHS[monthIndex]; | |
current[month] = Object.assign(current[month] ?? [], { | |
month, | |
}); | |
current[month].push(transaction); | |
return current; | |
}, {}); | |
setTransactions(prev => ({ ...prev, ...result })); | |
}; | |
useEffect(() => { | |
const lastPage = data?.pages?.[data?.pages?.length - 1].data ?? []; | |
if (orderBy === SETTINGS.ALL.value ?? lastPage.length) { | |
setTransactions(prev => { | |
prev[ALL_TRANSACTIONS_KEY].push(...lastPage); | |
return prev; | |
}); | |
} else { | |
transform(lastPage); | |
} | |
}, [orderBy, data?.pages]); | |
return { | |
transactions, | |
...query, | |
}; | |
}; | |
export default useTransactions; | |
// Component | |
import React from 'react'; | |
import { Dimensions, RefreshControl, ScrollView, View } from 'react-native'; | |
import styled, { useTheme } from 'styled-components/native'; | |
import i18n from '@helpers/i18n'; | |
import { useLayout } from '@react-native-community/hooks'; | |
import { Typography } from '@ui-kit/Typography'; | |
import TransactionsSkeletons from '../../shared/components/skeletons'; | |
import Transaction from '../../shared/components/WalletListItemTransaction'; | |
import useTransactions from '../hooks/useTransactions'; | |
import Separator from './Separator'; | |
// import Separator from './Separator'; | |
interface Props { | |
settings: any; | |
} | |
const renderSkeletons = (items: number) => <TransactionsSkeletons items={items} />; | |
const OFFSET = 50; | |
const { height: SCREEN_HEIGHT } = Dimensions.get('window'); | |
const TransactionList = ({ settings }: Props) => { | |
const { | |
transactions, | |
isLoading, | |
isFetchingNextPage, | |
fetchNextPage, | |
refetch, | |
hasNextPage, | |
isRefetching, | |
} = useTransactions(settings.value); | |
const { height: scrollViewHeight, onLayout } = useLayout(); | |
const { | |
utils: { statusBarHeight }, | |
} = useTheme(); | |
const transactionsListRef = React.useRef<ScrollView | null>(null); | |
const onRefetchNextPage = ({ | |
nativeEvent: { contentSize, layoutMeasurement, contentOffset }, | |
}) => { | |
if (layoutMeasurement.height + contentOffset.y >= contentSize.height - OFFSET && hasNextPage) { | |
fetchNextPage(); | |
} | |
}; | |
const showLoadMore = scrollViewHeight < SCREEN_HEIGHT + statusBarHeight()! && !isFetchingNextPage; | |
const onRefetch = () => fetchNextPage(); | |
const transactionList = Object.entries(transactions); | |
const hasTransactions = !!transactionList[0][1].length; | |
if (!isFetchingNextPage && isRefetching) { | |
return renderSkeletons(8); | |
} | |
if (!hasTransactions) { | |
console.log('no data'); | |
return <Typography>No data</Typography>; | |
} | |
if (hasTransactions) { | |
console.log('data'); | |
} | |
return ( | |
<View style={{ backgroundColor: 'red' }}> | |
{console.log(hasTransactions)} | |
<ScrollView | |
refreshControl={<RefreshControl refreshing={isLoading} onRefresh={refetch} />} | |
showsVerticalScrollIndicator={false} | |
onMomentumScrollEnd={onRefetchNextPage} | |
ref={transactionsListRef} | |
onContentSizeChange={() => transactionsListRef.current?.scrollToEnd({ animated: true })} | |
> | |
<View onLayout={onLayout}> | |
{ | |
<> | |
{transactionList.map(([header, item]) => ( | |
<React.Fragment key={header}> | |
<> | |
<Separator title={header} /> | |
{item.map(transaction => ( | |
<Transaction key={transaction!.id} {...transaction} /> | |
))} | |
</> | |
</React.Fragment> | |
))} | |
</> | |
} | |
</View> | |
{showLoadMore && ( | |
<StyledTypography color="textQuaternary" onPress={onRefetch}> | |
{i18n.t('misc.loadMore')} | |
</StyledTypography> | |
)} | |
{isFetchingNextPage && renderSkeletons(3)} | |
</ScrollView> | |
</View> | |
); | |
}; | |
export default TransactionList; | |
const StyledTypography = styled(Typography)` | |
margin: 0 auto; | |
`; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment