Skip to content

Instantly share code, notes, and snippets.

@emmacv
Last active August 26, 2022 08:36
Show Gist options
  • Save emmacv/52083b0c70224baecfcd8197ed49c6df to your computer and use it in GitHub Desktop.
Save emmacv/52083b0c70224baecfcd8197ed49c6df to your computer and use it in GitHub Desktop.
Gist to demonstrate the behaviour this component render.
// 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