Skip to content

Commit f013b34

Browse files
authored
Merge pull request #183 from ameerul-deriv/FEQ-2382-keep-the-filter-options-in-buy-sell-page
Ameerul / FEQ-2382 keep the filter options in buy sell page
2 parents a027d22 + 0930e9f commit f013b34

File tree

16 files changed

+220
-123
lines changed

16 files changed

+220
-123
lines changed

package-lock.json

Lines changed: 37 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@
5151
"use-query-params": "^2.2.1",
5252
"usehooks-ts": "^2.16.0",
5353
"vite": "^5.1.4",
54-
"vite-plugin-svgr": "^4.2.0"
54+
"vite-plugin-svgr": "^4.2.0",
55+
"zustand": "^4.5.2"
5556
},
5657
"devDependencies": {
5758
"@babel/plugin-proposal-class-properties": "^7.18.6",

src/components/Modals/FilterModal/FilterModal.tsx

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { useEffect, useState } from 'react';
22
import clsx from 'clsx';
3+
import { useShallow } from 'zustand/react/shallow';
34
import { FullPageMobileWrapper, PageReturn } from '@/components';
45
import { api, useModalManager } from '@/hooks';
6+
import { useBuySellFiltersStore } from '@/stores';
57
import { LabelPairedChevronRightLgRegularIcon } from '@deriv/quill-icons';
68
import { useTranslations } from '@deriv-com/translations';
79
import { Modal, Text, ToggleSwitch, useDevice } from '@deriv-com/ui';
@@ -12,29 +14,28 @@ import './FilterModal.scss';
1214

1315
type TFilterModalProps = {
1416
isModalOpen: boolean;
15-
isToggled: boolean;
1617
onRequestClose: () => void;
17-
onToggle: (value: boolean) => void;
18-
selectedPaymentMethods: string[];
19-
setSelectedPaymentMethods: (value: string[]) => void;
2018
};
2119

22-
const FilterModal = ({
23-
isModalOpen,
24-
isToggled,
25-
onRequestClose,
26-
onToggle,
27-
selectedPaymentMethods,
28-
setSelectedPaymentMethods,
29-
}: TFilterModalProps) => {
20+
const FilterModal = ({ isModalOpen, onRequestClose }: TFilterModalProps) => {
3021
const { hideModal, isModalOpenFor, showModal } = useModalManager();
3122
const { data } = api.paymentMethods.useGet();
3223
const { localize } = useTranslations();
33-
const [showPaymentMethods, setShowPaymentMethods] = useState<boolean>(false);
34-
const [isMatching, setIsMatching] = useState<boolean>(isToggled);
35-
const [paymentMethods, setPaymentMethods] = useState<string[]>(selectedPaymentMethods);
36-
const [paymentMethodNames, setPaymentMethodNames] = useState<string>('All');
3724
const { isMobile } = useDevice();
25+
const { selectedPaymentMethods, setSelectedPaymentMethods, setShouldUseClientLimits, shouldUseClientLimits } =
26+
useBuySellFiltersStore(
27+
useShallow(state => ({
28+
selectedPaymentMethods: state.selectedPaymentMethods,
29+
setSelectedPaymentMethods: state.setSelectedPaymentMethods,
30+
setShouldUseClientLimits: state.setShouldUseClientLimits,
31+
shouldUseClientLimits: state.shouldUseClientLimits,
32+
}))
33+
);
34+
35+
const [showPaymentMethods, setShowPaymentMethods] = useState(false);
36+
const [isMatching, setIsMatching] = useState(shouldUseClientLimits);
37+
const [paymentMethods, setPaymentMethods] = useState<string[]>(selectedPaymentMethods);
38+
const [paymentMethodNames, setPaymentMethodNames] = useState('All');
3839
const [isHidden, setIsHidden] = useState(false);
3940

4041
const filterOptions = [
@@ -54,7 +55,7 @@ const FilterModal = ({
5455
const sortedSelectedPaymentMethods = [...selectedPaymentMethods].sort((a, b) => a.localeCompare(b));
5556
const sortedPaymentMethods = [...paymentMethods].sort((a, b) => a.localeCompare(b));
5657
const hasSamePaymentMethods = JSON.stringify(sortedSelectedPaymentMethods) === JSON.stringify(sortedPaymentMethods);
57-
const hasSameMatching = isToggled === isMatching;
58+
const hasSameMatching = shouldUseClientLimits === isMatching;
5859
const hasSameFilters = hasSamePaymentMethods && hasSameMatching;
5960
const headerText = showPaymentMethods ? localize('Payment methods') : localize('Filter');
6061

@@ -63,7 +64,7 @@ const FilterModal = ({
6364
setShowPaymentMethods(false);
6465
} else {
6566
setSelectedPaymentMethods(paymentMethods);
66-
onToggle(isMatching);
67+
setShouldUseClientLimits(isMatching);
6768
onRequestClose();
6869
}
6970
};

src/components/Modals/FilterModal/__tests__/FilterModal.spec.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ import FilterModal from '../FilterModal';
55

66
const mockProps = {
77
isModalOpen: true,
8-
isToggled: true,
98
onRequestClose: jest.fn(),
10-
onToggle: jest.fn(),
11-
selectedPaymentMethods: [],
12-
setSelectedPaymentMethods: jest.fn(),
139
};
1410

1511
let mockData: { display_name: string; id: string }[] | undefined = [
@@ -40,6 +36,17 @@ jest.mock('@/hooks', () => ({
4036
useModalManager: jest.fn(() => mockModalManager),
4137
}));
4238

39+
const mockStore = {
40+
selectedPaymentMethods: [],
41+
setSelectedPaymentMethods: jest.fn(),
42+
setShouldUseClientLimits: jest.fn(),
43+
shouldUseClientLimits: true,
44+
};
45+
46+
jest.mock('@/stores', () => ({
47+
useBuySellFiltersStore: jest.fn(() => mockStore),
48+
}));
49+
4350
jest.mock('@deriv-com/ui', () => ({
4451
...jest.requireActual('@deriv-com/ui'),
4552
useDevice: jest.fn().mockReturnValue({
@@ -99,8 +106,8 @@ describe('<FilterModal />', () => {
99106
await user.click(toggleSwitch);
100107
await user.click(applyButton);
101108

102-
expect(mockProps.setSelectedPaymentMethods).toHaveBeenCalled();
103-
expect(mockProps.onToggle).toHaveBeenCalled();
109+
expect(mockStore.setSelectedPaymentMethods).toHaveBeenCalled();
110+
expect(mockStore.setShouldUseClientLimits).toHaveBeenCalled();
104111
expect(mockProps.onRequestClose).toHaveBeenCalled();
105112
});
106113

@@ -115,7 +122,7 @@ describe('<FilterModal />', () => {
115122

116123
await user.click(resetButton);
117124

118-
expect(mockProps.setSelectedPaymentMethods).toHaveBeenCalled();
125+
expect(mockStore.setSelectedPaymentMethods).toHaveBeenCalled();
119126
expect(toggleSwitch).toBeChecked();
120127
});
121128

@@ -259,7 +266,7 @@ describe('<FilterModal />', () => {
259266
await user.click(alipayCheckbox);
260267
await user.click(alipayCheckbox);
261268

262-
expect(mockProps.setSelectedPaymentMethods).toHaveBeenCalled();
269+
expect(mockStore.setSelectedPaymentMethods).toHaveBeenCalled();
263270
});
264271

265272
it('should populate the payment methods list with the data from the API', async () => {

src/components/Modals/RadioGroupFilterModal/RadioGroupFilterModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type TRadioGroupFilterModalProps = {
77
list: readonly { text: string; value: string }[];
88
onRequestClose: () => void;
99
onToggle: (value: string) => void;
10-
selected: string;
10+
selected?: string;
1111
};
1212

1313
const RadioGroupFilterModal = ({

src/components/RadioGroup/RadioGroup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type TRadioGroup = TItemWrapper & {
1919
name: string;
2020
onToggle: (e: ChangeEvent<HTMLInputElement>) => void;
2121
required?: boolean;
22-
selected: string;
22+
selected?: string;
2323
textSize?: ComponentProps<typeof Text>['size'];
2424
};
2525

src/hooks/custom-hooks/__tests__/useAdvertiserStats.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ jest.mock('@deriv-com/api-hooks', () => ({
3838
jest.mock('@/hooks', () => ({
3939
api: {
4040
account: {
41+
useActiveAccount: jest.fn(() => ({
42+
data: { currency: 'USD' },
43+
})),
4144
useAuthentication: jest.fn(() => mockUseAuthentication),
4245
},
4346
advertiser: {

src/hooks/custom-hooks/useAdvertiserStats.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ const toAdvertiserMinutes = (duration?: number | null) => {
2222
* @param advertiserId - ID of the advertiser stats to reveal. If not provided, by default it will return the user's own stats.
2323
*/
2424
const useAdvertiserStats = (advertiserId?: string) => {
25-
const { data, subscribe, unsubscribe } = api.advertiser.useGetInfo(advertiserId);
25+
const { data, isLoading: isLoadingInfo, subscribe, unsubscribe } = api.advertiser.useGetInfo(advertiserId);
2626
const { data: settings, isSuccess: isSuccessSettings } = useGetSettings();
2727
const { data: authenticationStatus, isSuccess: isSuccessAuthenticationStatus } = api.account.useAuthentication();
28+
const { data: activeAccountData } = api.account.useActiveAccount();
2829
const { error, isIdle, isLoading, isSubscribed } = useAdvertiserInfoState();
2930

3031
useEffect(() => {
31-
if (advertiserId) {
32+
if (advertiserId && activeAccountData) {
3233
subscribe({ id: advertiserId });
3334
}
3435
// eslint-disable-next-line react-hooks/exhaustive-deps
35-
}, [advertiserId]);
36+
}, [advertiserId, activeAccountData]);
3637

3738
useEffect(() => {
3839
return () => {
@@ -129,7 +130,7 @@ const useAdvertiserStats = (advertiserId?: string) => {
129130
data: transformedData,
130131
error,
131132
isIdle,
132-
isLoading,
133+
isLoading: advertiserId ? isLoadingInfo : isLoading,
133134
isSubscribed,
134135
unsubscribe,
135136
};

src/pages/advertiser/screens/Advertiser/Advertiser.tsx

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import BlockDropdown from '@/components/AdvertiserName/BlockDropdown';
55
import { BUY_SELL_URL, MY_PROFILE_URL } from '@/constants';
66
import { api, useAdvertiserStats, useModalManager } from '@/hooks';
77
import { useTranslations } from '@deriv-com/translations';
8-
import { useDevice } from '@deriv-com/ui';
8+
import { Loader, useDevice } from '@deriv-com/ui';
99
import { AdvertiserAdvertsTable } from '../AdvertiserAdvertsTable';
1010
import { AdvertiserBlockOverlay } from '../AdvertiserBlockOverlay';
1111
import './Advertiser.scss';
@@ -25,7 +25,7 @@ const Advertiser = () => {
2525
const history = useHistory();
2626
const location = useLocation();
2727

28-
const { data, unsubscribe } = useAdvertiserStats(id);
28+
const { data, isLoading, unsubscribe } = useAdvertiserStats(id);
2929

3030
return (
3131
<div className='advertiser'>
@@ -54,16 +54,20 @@ const Advertiser = () => {
5454
size={isMobile ? 'lg' : 'md'}
5555
weight='bold'
5656
/>
57-
<AdvertiserBlockOverlay
58-
advertiserName={advertiserName}
59-
id={id}
60-
isOverlayVisible={showOverlay}
61-
onClickUnblock={() => showModal('BlockUnblockUserModal')}
62-
setShowOverlay={setShowOverlay}
63-
>
64-
<ProfileContent data={data} setAdvertiserName={setAdvertiserName} setShowOverlay={setShowOverlay} />
65-
<AdvertiserAdvertsTable advertiserId={advertiserId} />
66-
</AdvertiserBlockOverlay>
57+
{isLoading ? (
58+
<Loader className='mt-0 lg:mt-80' />
59+
) : (
60+
<AdvertiserBlockOverlay
61+
advertiserName={advertiserName}
62+
id={id}
63+
isOverlayVisible={showOverlay}
64+
onClickUnblock={() => showModal('BlockUnblockUserModal')}
65+
setShowOverlay={setShowOverlay}
66+
>
67+
<ProfileContent data={data} setAdvertiserName={setAdvertiserName} setShowOverlay={setShowOverlay} />
68+
<AdvertiserAdvertsTable advertiserId={advertiserId} />
69+
</AdvertiserBlockOverlay>
70+
)}
6771
</div>
6872
);
6973
};

0 commit comments

Comments
 (0)