diff --git a/packages/components/src/components/data-list/data-list.tsx b/packages/components/src/components/data-list/data-list.tsx index f32a326be2d1..4f0b0331069c 100644 --- a/packages/components/src/components/data-list/data-list.tsx +++ b/packages/components/src/components/data-list/data-list.tsx @@ -1,5 +1,5 @@ -import classNames from 'classnames'; import React from 'react'; +import classNames from 'classnames'; import { TransitionGroup } from 'react-transition-group'; import { List as _List, @@ -8,7 +8,6 @@ import { CellMeasurerProps, AutoSizer as _AutoSizer, type AutoSizerProps, - ScrollParams, ListProps, ListRowProps, } from 'react-virtualized'; @@ -26,7 +25,8 @@ export type TPassThrough = { isTopUp: (item: TRow) => boolean }; export type TRow = { [key: string]: string; }; -type DataListProps = { + +type TDataList = { className?: string; data_source: TRow[]; footer?: React.ReactNode; @@ -34,7 +34,7 @@ type DataListProps = { getRowSize?: (params: { index: number }) => number; keyMapper?: (row: TRow) => number | string; onRowsRendered?: () => void; - onScroll?: (ev: ScrollParams) => void; + onScroll?: React.UIEventHandler; passthrough?: TPassThrough; row_gap?: number; setListRef?: (ref: MeasuredCellParent) => void; @@ -44,196 +44,183 @@ type DataListProps = { }; type GetContentType = { measure?: () => void | undefined }; -const DataList = ({ - children, - className, - data_source, - footer, - getRowSize, - keyMapper, - onRowsRendered, - onScroll, - setListRef, - overscanRowCount, - rowRenderer: rowRendererProp, - row_gap, - getRowAction, - passthrough, -}: DataListProps) => { - const [is_loading, setLoading] = React.useState(true); - const [is_scrolling, setIsScrolling] = React.useState(false); - const [scroll_top, setScrollTop] = React.useState(0); - - const cache = React.useRef(); - const list_ref = React.useRef(null); - const items_transition_map_ref = React.useRef<{ [key: string]: boolean }>({}); - const data_source_ref = React.useRef(null); - data_source_ref.current = data_source; - - const is_dynamic_height = !getRowSize; - - const trackItemsForTransition = React.useCallback(() => { - data_source.forEach((item: TRow, index: number) => { - const row_key: string | number = keyMapper?.(item) || `${index}-0`; - items_transition_map_ref.current[row_key] = true; - }); - }, [data_source, keyMapper]); - - React.useEffect(() => { - if (is_dynamic_height) { - cache.current = new CellMeasurerCache({ - fixedWidth: true, - keyMapper: row_index => { - if (data_source_ref?.current && row_index < data_source_ref?.current.length) - return keyMapper?.(data_source_ref.current[row_index]) || row_index; - return row_index; - }, +const DataList = React.memo( + ({ + children, + className, + data_source, + footer, + getRowSize, + keyMapper, + onRowsRendered, + onScroll, + setListRef, + overscanRowCount, + ...other_props + }: TDataList) => { + const [is_loading, setLoading] = React.useState(true); + const [is_scrolling, setIsScrolling] = React.useState(false); + const [scroll_top, setScrollTop] = React.useState(0); + + const cache = React.useRef(); + const list_ref = React.useRef(null); + const items_transition_map_ref = React.useRef<{ [key: string]: boolean }>({}); + const data_source_ref = React.useRef(null); + data_source_ref.current = data_source; + + const is_dynamic_height = !getRowSize; + + const trackItemsForTransition = React.useCallback(() => { + data_source.forEach((item: TRow, index: number) => { + const row_key: string | number = keyMapper?.(item) || `${index}-0`; + items_transition_map_ref.current[row_key] = true; }); - } - trackItemsForTransition(); - setLoading(false); - }, []); // eslint-disable-line react-hooks/exhaustive-deps - - React.useEffect(() => { - if (is_dynamic_height) { - list_ref.current?.recomputeGridSize?.({ columnIndex: 0, rowIndex: 0 }); - } - trackItemsForTransition(); - }, [data_source, is_dynamic_height, trackItemsForTransition]); - - const footerRowRenderer = () => { - return {rowRendererProp({ row: footer, is_footer: true })}; - }; - - const rowRenderer = ({ style, index, key, parent }: ListRowProps) => { - const row = data_source[index]; - const action = getRowAction && getRowAction(row); - const destination_link = typeof action === 'string' ? action : undefined; - const action_desc = typeof action === 'object' ? action : undefined; - const row_key = keyMapper?.(row) || key; - - const getContent = ({ measure }: GetContentType = {}) => ( - - ); + }, [data_source, keyMapper]); + + React.useEffect(() => { + if (is_dynamic_height) { + cache.current = new CellMeasurerCache({ + fixedWidth: true, + keyMapper: row_index => { + if (data_source_ref?.current && row_index < data_source_ref?.current.length) + return keyMapper?.(data_source_ref.current[row_index]) || row_index; + return row_index; + }, + }); + } + trackItemsForTransition(); + setLoading(false); + }, []); // eslint-disable-line react-hooks/exhaustive-deps - return is_dynamic_height && cache.current ? ( - - {({ measure }) =>
{getContent({ measure })}
} -
- ) : ( -
- {getContent()} -
- ); - }; - let timeout: ReturnType; - const handleScroll = (e: ScrollParams): void => { - const { scrollTop } = e; - - clearTimeout(timeout); - if (!is_scrolling) { - setIsScrolling(true); - } - timeout = setTimeout(() => { - if (!is_loading) { - setIsScrolling(false); + React.useEffect(() => { + if (is_dynamic_height) { + list_ref.current?.recomputeGridSize?.({ columnIndex: 0, rowIndex: 0 }); } - }, 200); + trackItemsForTransition(); + }, [data_source, is_dynamic_height, trackItemsForTransition]); + + const footerRowRenderer = () => { + return {other_props.rowRenderer({ row: footer, is_footer: true })}; + }; + + const rowRenderer = ({ style, index, key, parent }: ListRowProps) => { + const { getRowAction, passthrough, row_gap } = other_props; + const row = data_source[index]; + const action = getRowAction && getRowAction(row); + const destination_link = typeof action === 'string' ? action : undefined; + const action_desc = typeof action === 'object' ? action : undefined; + const row_key = keyMapper?.(row) || key; + + const getContent = ({ measure }: GetContentType = {}) => ( + + ); + + return is_dynamic_height && cache.current ? ( + + {({ measure }) =>
{getContent({ measure })}
} +
+ ) : ( +
+ {getContent()} +
+ ); + }; - setScrollTop(scrollTop); - onScroll?.(e); - }; + const handleScroll: React.UIEventHandler = ev => { + let timeout; - const setRef = (ref: MeasuredCellParent) => { - list_ref.current = ref; - setListRef?.(ref); - }; + clearTimeout(timeout); + if (!is_scrolling) { + setIsScrolling(true); + } + timeout = setTimeout(() => { + if (!is_loading) { + setIsScrolling(false); + } + }, 200); + + setScrollTop((ev.target as HTMLElement).scrollTop); + if (typeof onScroll === 'function') { + onScroll(ev); + } + }; - if (is_loading) { - return
; - } - return ( -
-
-
- - {({ width, height }) => ( - // Don't remove `TransitionGroup`. When `TransitionGroup` is removed, transition life cycle events like `onEntered` won't be fired sometimes on it's `CSSTransition` children - - { - const event = { - clientHeight: e.currentTarget.clientHeight, - clientWidth: e.currentTarget.clientWidth, - scrollHeight: e.currentTarget.scrollHeight, - scrollLeft: e.currentTarget.scrollLeft, - scrollTop: e.currentTarget.scrollTop, - scrollWidth: e.currentTarget.scrollWidth, - }; - handleScroll(event); - }} - autohide - is_bypassed={isMobile()} - > - setRef(ref)} - rowCount={data_source.length} - rowHeight={ - is_dynamic_height && cache?.current?.rowHeight - ? cache?.current?.rowHeight - : getRowSize || 0 - } - rowRenderer={rowRenderer} - scrollingResetTimeInterval={0} - width={width} - {...(isDesktop() - ? { scrollTop: scroll_top, autoHeight: true } - : { onScroll: target => handleScroll(target) })} - /> - - - )} - + const setRef = (ref: MeasuredCellParent) => { + list_ref.current = ref; + setListRef?.(ref); + }; + + if (is_loading) { + return
; + } + return ( +
+
+
+ + {({ width, height }) => ( + // Don't remove `TransitionGroup`. When `TransitionGroup` is removed, transition life cycle events like `onEntered` won't be fired sometimes on it's `CSSTransition` children + + + setRef(ref)} + rowCount={data_source.length} + rowHeight={ + is_dynamic_height && cache?.current?.rowHeight + ? cache?.current?.rowHeight + : getRowSize || 0 + } + rowRenderer={rowRenderer} + scrollingResetTimeInterval={0} + width={width} + {...(isDesktop() + ? { scrollTop: scroll_top, autoHeight: true } + : { onScroll: target => handleScroll({ target } as any) })} + /> + + + )} + +
+ {children}
- {children} + {footer && ( +
+ {footerRowRenderer()} +
+ )}
- {footer && ( -
- {footerRowRenderer()} -
- )} -
- ); -}; + ); + } +); DataList.displayName = 'DataList'; +(DataList as any).Cell = DataListCell; -DataList.Cell = DataListCell; -const genericMemo: (component: T) => T = React.memo; -export default genericMemo(DataList); +export default DataList; diff --git a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx index 4b7048792615..114a70236f4b 100644 --- a/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx +++ b/packages/core/src/App/Containers/Modals/trading-assessment-existing-user.jsx @@ -17,6 +17,8 @@ const TradingAssessmentExistingUser = ({ setShouldShowAssessmentCompleteModal, setIsTradingAssessmentForExistingUserEnabled, setIsTradingAssessmentForNewUserEnabled, + setShouldShowTradingAssessmentModal, + setSubSectionIndex, }) => { // Get the Trading assessment questions and initial_value const [form_values, setFormValue] = React.useState({}); @@ -63,6 +65,11 @@ const TradingAssessmentExistingUser = ({ setShouldShowTradeAssessmentForm(true); }; + const handleCancel = () => { + setShouldShowTradingAssessmentModal(true); + setShouldShowTradeAssessmentForm(false); + }; + if (should_show_risk_warning_modal) { return ( @@ -112,6 +121,8 @@ const TradingAssessmentExistingUser = ({ assessment_questions={assessment_questions} form_value={form_values} onSubmit={handleSubmit} + onCancel={handleCancel} + setSubSectionIndex={setSubSectionIndex} class_name='trading-assessment--existing-user' should_move_to_next={should_move_to_next} /> @@ -135,4 +146,6 @@ export default connect(({ client, ui }) => ({ setIsTradingAssessmentForExistingUserEnabled: ui.setIsTradingAssessmentForExistingUserEnabled, active_account_landing_company: client.landing_company_shortcode, setIsTradingAssessmentForNewUserEnabled: ui.setIsTradingAssessmentForNewUserEnabled, + setSubSectionIndex: ui.setSubSectionIndex, + setShouldShowTradingAssessmentModal: ui.setShouldShowTradingAssessmentModal, }))(TradingAssessmentExistingUser);