11import './BTCTransactionsList.scss' ;
2- import { useState } from 'react' ;
2+ import { useCallback , useEffect , useRef , useState } from 'react' ;
33import { motion , AnimatePresence } from 'framer-motion' ;
44import { Spinner , Alert , Row , Col } from 'react-bootstrap' ;
5+ import PerfectScrollbar from 'react-perfect-scrollbar' ;
56
67import { formatCurrency , titleCase } from '../../../utilities/data-formatters' ;
78import { IncomingArrowSVG } from '../../../svgs/IncomingArrow' ;
89import { OutgoingArrowSVG } from '../../../svgs/OutgoingArrow' ;
910import DateBox from '../../shared/DateBox/DateBox' ;
1011import FiatBox from '../../shared/FiatBox/FiatBox' ;
1112import Transaction from '../BTCTransaction/BTCTransaction' ;
12- import { TRANSITION_DURATION , Units } from '../../../utilities/constants' ;
13+ import { SCROLL_BATCH_SIZE , SCROLL_THRESHOLD , TRANSITION_DURATION , Units } from '../../../utilities/constants' ;
1314import { NoBTCTransactionDarkSVG } from '../../../svgs/NoBTCTransactionDark' ;
1415import { NoBTCTransactionLightSVG } from '../../../svgs/NoBTCTransactionLight' ;
1516import { useSelector } from 'react-redux' ;
@@ -178,6 +179,69 @@ export const BTCTransactionsList = () => {
178179 const initExpansions = ( listBitcoinTransactions . btcTransactions ?. reduce ( ( acc : boolean [ ] ) => [ ...acc , false ] , [ ] ) || [ ] ) ;
179180 const [ expanded , setExpanded ] = useState < boolean [ ] > ( initExpansions ) ;
180181
182+ const [ displayedTransactions , setDisplayedTransactions ] = useState < any [ ] > ( [ ] ) ;
183+ const [ currentIndex , setCurrentIndex ] = useState ( 0 ) ;
184+ const [ isLoading , setIsLoading ] = useState ( false ) ;
185+ const [ allTransactionsLoaded , setAllTransactionsLoaded ] = useState ( false ) ;
186+ const containerRef = useRef < HTMLDivElement > ( null ) ;
187+
188+ const setContainerRef = useCallback ( ( ref : HTMLElement | null ) => {
189+ if ( ref ) {
190+ ( containerRef as React . MutableRefObject < HTMLElement | null > ) . current = ref ;
191+ }
192+ } , [ ] ) ;
193+
194+ useEffect ( ( ) => {
195+ if ( listBitcoinTransactions ?. btcTransactions ?. length > 0 ) {
196+ const initialBatch = listBitcoinTransactions ?. btcTransactions . slice ( 0 , SCROLL_BATCH_SIZE ) ;
197+ console . warn ( 'Initial batch of transactions:' , initialBatch ) ;
198+ setDisplayedTransactions ( initialBatch ) ;
199+ setCurrentIndex ( SCROLL_BATCH_SIZE ) ;
200+ if ( SCROLL_BATCH_SIZE >= listBitcoinTransactions ?. btcTransactions . length ) {
201+ setAllTransactionsLoaded ( true ) ;
202+ }
203+ }
204+ } , [ listBitcoinTransactions ] ) ;
205+
206+ const loadMoreTransactions = useCallback ( ( ) => {
207+ if ( isLoading || allTransactionsLoaded ) return ;
208+ setIsLoading ( true ) ;
209+ setTimeout ( ( ) => {
210+ const nextIndex = currentIndex + SCROLL_BATCH_SIZE ;
211+ const newTransactions = listBitcoinTransactions ?. btcTransactions . slice (
212+ currentIndex ,
213+ nextIndex
214+ ) ;
215+ setDisplayedTransactions ( prev => [ ...prev , ...newTransactions ] ) ;
216+ setCurrentIndex ( nextIndex ) ;
217+
218+ if ( nextIndex >= listBitcoinTransactions ?. btcTransactions . length ) {
219+ setAllTransactionsLoaded ( true ) ;
220+ }
221+
222+ setIsLoading ( false ) ;
223+ } , 300 ) ;
224+ } , [ currentIndex , isLoading , allTransactionsLoaded , listBitcoinTransactions ] ) ;
225+
226+ const handleScroll = useCallback ( ( container ) => {
227+ if ( ! container || isLoading || allTransactionsLoaded ) return ;
228+
229+ const { scrollTop, scrollHeight, clientHeight } = container ;
230+ const bottomOffset = scrollHeight - scrollTop - clientHeight ;
231+
232+ if ( bottomOffset < SCROLL_THRESHOLD ) {
233+ loadMoreTransactions ( ) ;
234+ }
235+ } , [ isLoading , allTransactionsLoaded , loadMoreTransactions ] ) ;
236+
237+ useEffect ( ( ) => {
238+ const container = containerRef . current ;
239+ if ( container ) {
240+ container ?. addEventListener ( 'scroll' , handleScroll ) ;
241+ return ( ) => container ?. removeEventListener ( 'scroll' , handleScroll ) ;
242+ }
243+ } , [ handleScroll ] ) ;
244+
181245 return (
182246 isAuthenticated && listBitcoinTransactions . isLoading ?
183247 < span className = 'h-100 d-flex justify-content-center align-items-center' >
@@ -187,13 +251,28 @@ export const BTCTransactionsList = () => {
187251 listBitcoinTransactions . error ?
188252 < Alert className = 'py-0 px-1 fs-7' variant = 'danger' > { listBitcoinTransactions . error } </ Alert > :
189253 listBitcoinTransactions ?. btcTransactions && listBitcoinTransactions ?. btcTransactions . length && listBitcoinTransactions ?. btcTransactions . length > 0 ?
190- < div className = 'btc-transactions-list' data-testid = 'btc-transactions-list' >
191- {
192- listBitcoinTransactions ?. btcTransactions ?. map ( ( transaction , i ) => (
193- < BTCTransactionsAccordion key = { i } i = { i } expanded = { expanded } setExpanded = { setExpanded } initExpansions = { initExpansions } transaction = { transaction } />
194- ) )
254+ < PerfectScrollbar
255+ containerRef = { setContainerRef }
256+ onScrollY = { handleScroll }
257+ className = 'btc-transactions-list'
258+ data-testid = 'btc-transactions-list'
259+ options = { {
260+ suppressScrollX : true ,
261+ wheelPropagation : false
262+ } }
263+ >
264+ { displayedTransactions . map ( ( transaction , i ) => (
265+ < BTCTransactionsAccordion key = { i } i = { i } expanded = { expanded } setExpanded = { setExpanded } initExpansions = { initExpansions } transaction = { transaction } />
266+ ) ) }
267+ { isLoading && (
268+ < Col xs = { 12 } className = 'd-flex align-items-center justify-content-center mb-5' >
269+ < Spinner animation = 'grow' variant = 'primary' />
270+ </ Col >
271+ ) }
272+ { allTransactionsLoaded && listBitcoinTransactions ?. btcTransactions . length > 100 &&
273+ < h6 className = 'd-flex align-self-center py-4 text-muted' > No more transactions to load!</ h6 >
195274 }
196- </ div >
275+ </ PerfectScrollbar >
197276 :
198277 < Row className = 'text-light fs-6 h-75 mt-2 align-items-center justify-content-center' >
199278 < Row className = 'd-flex align-items-center justify-content-center' >
0 commit comments