-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ameerul / P2PS-4363 Banner on Buy/Sell page #401
base: master
Are you sure you want to change the base?
Changes from 5 commits
1695fa2
bfc0ea4
59a0be6
6ce829e
f122deb
7464cc4
6ecd646
816426e
bd0c708
b10b72d
2760fd7
d030c3d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
.funds-banner { | ||
@include mobile-or-tablet-screen { | ||
padding: 1.6rem 1.6rem 0.8rem; | ||
} | ||
|
||
&__inline-message { | ||
background-color: rgba(44, 154, 255, 0.08); | ||
border-radius: 1.6rem; | ||
padding: 1.6rem; | ||
margin-bottom: 1.5rem; | ||
|
||
@include mobile-or-tablet-screen { | ||
margin-bottom: 0; | ||
} | ||
|
||
&__button { | ||
padding: 0; | ||
text-decoration: underline; | ||
cursor: pointer; | ||
|
||
&:hover { | ||
background-color: transparent !important; | ||
|
||
& > span { | ||
color: #0e0e0e !important; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.deriv-inline-message__icon { | ||
width: 24px; | ||
height: 24px; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { FundsModal } from '@/components/Modals'; | ||
import { useModalManager } from '@/hooks/custom-hooks'; | ||
import { LabelPairedCircleInfoLgBoldIcon } from '@deriv/quill-icons'; | ||
import { Localize } from '@deriv-com/translations'; | ||
import { Button, InlineMessage, Text, useDevice } from '@deriv-com/ui'; | ||
import './FundsBanner.scss'; | ||
|
||
const FundsBanner = () => { | ||
const { isDesktop } = useDevice(); | ||
const { hideModal, isModalOpenFor, showModal } = useModalManager(); | ||
const textSize = isDesktop ? 'sm' : 'md'; | ||
|
||
return ( | ||
<div className='funds-banner'> | ||
<InlineMessage | ||
className='funds-banner__inline-message' | ||
icon={<LabelPairedCircleInfoLgBoldIcon fill='#0777C4' height={24} width={24} />} | ||
iconPosition='center' | ||
> | ||
<div> | ||
<Text className='mr-1' size={textSize}> | ||
<Localize i18n_default_text='Your P2P funds are accessible through your Options trading account.' /> | ||
</Text> | ||
<Button | ||
className='funds-banner__inline-message__button' | ||
color='black' | ||
hideHoverStyles | ||
onClick={() => showModal('FundsModal')} | ||
textSize={textSize} | ||
variant='ghost' | ||
> | ||
<Localize i18n_default_text='Learn more' /> | ||
</Button> | ||
</div> | ||
</InlineMessage> | ||
{!!isModalOpenFor('FundsModal') && <FundsModal isModalOpen onRequestClose={hideModal} />} | ||
</div> | ||
); | ||
}; | ||
|
||
export default FundsBanner; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { fireEvent, render, screen } from '@testing-library/react'; | ||
import FundsBanner from '../FundsBanner'; | ||
|
||
const mockModalManager = { | ||
hideModal: jest.fn(), | ||
isModalOpenFor: jest.fn().mockReturnValue(false), | ||
showModal: jest.fn(), | ||
}; | ||
|
||
jest.mock('@deriv-com/ui', () => ({ | ||
...jest.requireActual('@deriv-com/ui'), | ||
useDevice: jest.fn().mockReturnValue({ | ||
isMobile: false, | ||
}), | ||
})); | ||
|
||
jest.mock('@/hooks/custom-hooks', () => ({ | ||
useModalManager: jest.fn(() => mockModalManager), | ||
})); | ||
|
||
describe('<FundsBanner />', () => { | ||
it('should render the FundsBanner', () => { | ||
render(<FundsBanner />); | ||
|
||
expect( | ||
screen.getByText(/Your P2P funds are accessible through your Options trading account./) | ||
).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: /Learn more/ })).toBeInTheDocument(); | ||
}); | ||
|
||
it('should call showModal when the Learn more button is clicked and show the FundsModal', () => { | ||
render(<FundsBanner />); | ||
fireEvent.click(screen.getByRole('button', { name: /Learn more/ })); | ||
|
||
expect(mockModalManager.showModal).toHaveBeenCalledWith('FundsModal'); | ||
}); | ||
|
||
it('should render the FundsModal if it is open', () => { | ||
mockModalManager.isModalOpenFor.mockImplementation((modalName: string) => modalName === 'FundsModal'); | ||
render(<FundsBanner />); | ||
|
||
expect(screen.getByText('How to fund your trades?')).toBeInTheDocument(); | ||
expect(screen.getByText('For Options trading:')).toBeInTheDocument(); | ||
expect(screen.getByText('Trade directly with funds from your Options trading account.')).toBeInTheDocument(); | ||
expect(screen.getByText('For CFDs trading:')).toBeInTheDocument(); | ||
expect( | ||
screen.getByText('1. Transfer funds from your Options trading account to your USD Wallet.') | ||
).toBeInTheDocument(); | ||
expect( | ||
screen.getByText('2. Then, move the funds from your USD Wallet to your CFDs account.') | ||
).toBeInTheDocument(); | ||
expect(screen.getByRole('button', { name: 'OK' })).toBeInTheDocument(); | ||
}); | ||
|
||
it('should call hideModal when the OK button is clicked', () => { | ||
render(<FundsBanner />); | ||
|
||
fireEvent.click(screen.getByRole('button', { name: 'OK' })); | ||
expect(mockModalManager.hideModal).toHaveBeenCalled(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as FundsBanner } from './FundsBanner'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
.funds-modal { | ||
@include default-modal; | ||
|
||
&__header { | ||
padding-top: 1rem !important; | ||
|
||
@include mobile-or-tablet-screen { | ||
padding-top: 0 !important; | ||
padding-left: 1.6rem; | ||
ameerul-deriv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
&__body { | ||
display: flex; | ||
flex-direction: column; | ||
padding: 1rem 2.4rem; | ||
gap: 2.4rem; | ||
|
||
@include mobile-or-tablet-screen { | ||
padding: 0 1.6rem; | ||
} | ||
} | ||
|
||
&__footer { | ||
padding-bottom: 2.4rem; | ||
gap: 0.8rem; | ||
|
||
@include mobile-or-tablet-screen { | ||
padding-bottom: 1.6rem; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Localize } from '@deriv-com/translations'; | ||
import { Button, Modal, Text } from '@deriv-com/ui'; | ||
import './FundsModal.scss'; | ||
|
||
type TFundsModalProps = { | ||
isModalOpen: boolean; | ||
onRequestClose: () => void; | ||
}; | ||
|
||
const FundsModal = ({ isModalOpen, onRequestClose }: TFundsModalProps) => { | ||
return ( | ||
<Modal ariaHideApp={false} className='funds-modal' isOpen={isModalOpen} shouldCloseOnOverlayClick={false}> | ||
<Modal.Header className='funds-modal__header' hideBorder hideCloseIcon> | ||
<Text size='md' weight='bold'> | ||
<Localize i18n_default_text='How to fund your trades?' /> | ||
</Text> | ||
</Modal.Header> | ||
<Modal.Body className='funds-modal__body'> | ||
<div className='flex flex-col'> | ||
<Text size='sm' weight='bold'> | ||
<Localize i18n_default_text='For Options trading:' /> | ||
</Text> | ||
<Text size='sm'> | ||
<Localize i18n_default_text='Trade directly with funds from your Options trading account.' /> | ||
</Text> | ||
</div> | ||
<div className='flex flex-col'> | ||
<Text size='sm' weight='bold'> | ||
<Localize i18n_default_text='For CFDs trading:' /> | ||
</Text> | ||
<Text size='sm'> | ||
<Localize i18n_default_text='1. Transfer funds from your Options trading account to your USD Wallet.' /> | ||
</Text> | ||
<Text size='sm'> | ||
<Localize i18n_default_text='2. Then, move the funds from your USD Wallet to your CFDs account.' /> | ||
</Text> | ||
</div> | ||
</Modal.Body> | ||
<Modal.Footer className='funds-modal__footer' hideBorder> | ||
<Button onClick={() => onRequestClose()} size='lg' textSize='sm'> | ||
<Localize i18n_default_text='OK' /> | ||
</Button> | ||
</Modal.Footer> | ||
</Modal> | ||
); | ||
}; | ||
|
||
export default FundsModal; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as FundsModal } from './FundsModal'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ import clsx from 'clsx'; | |
import { TCurrencyListItem } from 'types'; | ||
import { useOnClickOutside } from 'usehooks-ts'; | ||
import { FullPageMobileWrapper } from '@/components'; | ||
import { api } from '@/hooks'; | ||
import { api, useQueryString } from '@/hooks'; | ||
import { LabelPairedChevronDownMdRegularIcon } from '@deriv/quill-icons'; | ||
import { Localize } from '@deriv-com/translations'; | ||
import { Text, useDevice } from '@deriv-com/ui'; | ||
|
@@ -19,6 +19,15 @@ const CurrencyDropdown = ({ selectedCurrency, setSelectedCurrency }: TCurrencyDr | |
const { data } = api.settings.useSettings(); | ||
const { isDesktop, isMobile } = useDevice(); | ||
const [showCurrencySelector, setShowCurrencySelector] = useState<boolean>(false); | ||
const { deleteQueryString, setQueryString } = useQueryString(); | ||
|
||
const onToggleCurrencyDropdown = (shouldShow: boolean) => { | ||
setShowCurrencySelector(shouldShow); | ||
if (!isDesktop) { | ||
if (shouldShow) setQueryString({ modal: 'CurrencyFilterModal' }); | ||
else deleteQueryString('modal'); | ||
} | ||
}; | ||
Comment on lines
+22
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reason why i added this queryString to modal directly is to ensure we hide the banner if currency selector is shown. And in the index.tsx file, I have some logic that handles showing the banner if its either the RadioGroupModal or FundsModal or if there is no Modal showing at all. Below you can see the issue Screen.Recording.2024-11-11.at.4.25.55.PM.movfix.movThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also you cannot use isModalOpenFor check because it only returns true in whatever component you have called showModal in |
||
|
||
const currencySelectorRef = useRef<HTMLDivElement>(null); | ||
useOnClickOutside(currencySelectorRef, () => { | ||
|
@@ -39,7 +48,7 @@ const CurrencyDropdown = ({ selectedCurrency, setSelectedCurrency }: TCurrencyDr | |
}, [data?.currencyList, selectedCurrency]) ?? []; | ||
|
||
const onSelectItem = (currency: string) => { | ||
setShowCurrencySelector(false); | ||
onToggleCurrencyDropdown(false); | ||
setSelectedCurrency(currency); | ||
}; | ||
|
||
|
@@ -48,7 +57,7 @@ const CurrencyDropdown = ({ selectedCurrency, setSelectedCurrency }: TCurrencyDr | |
<FullPageMobileWrapper | ||
className='currency-dropdown__full-page-modal' | ||
onBack={() => { | ||
setShowCurrencySelector(false); | ||
onToggleCurrencyDropdown(false); | ||
}} | ||
renderHeader={() => ( | ||
<Text size='lg' weight='bold'> | ||
|
@@ -70,7 +79,7 @@ const CurrencyDropdown = ({ selectedCurrency, setSelectedCurrency }: TCurrencyDr | |
className={clsx('currency-dropdown__dropdown', { | ||
'currency-dropdown__dropdown--active': showCurrencySelector, | ||
})} | ||
onClick={() => setShowCurrencySelector(prev => !prev)} | ||
onClick={() => onToggleCurrencyDropdown(!showCurrencySelector)} | ||
> | ||
<Text className='currency-dropdown__dropdown-text' size={isMobile ? 'xs' : '2xs'}> | ||
<Localize i18n_default_text='Currency' /> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even though I used hideHoverStyles in the button, it didn't work 😅 so i had to manually disable it here