Skip to content
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-464 [FE] - Mandatory Mobile Number Verification for Deriv P2P (New User) #400

Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/components/AdvertsTableRow/AdvertsTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useHistory, useLocation } from 'react-router-dom';
import { TAdvertsTableRowRenderer, TCurrency } from 'types';
import { Badge, BuySellForm, PaymentMethodLabel, StarRating, UserAvatar } from '@/components';
import { ErrorModal, NicknameModal } from '@/components/Modals';
import { ADVERTISER_URL, BUY_SELL } from '@/constants';
import { ADVERTISER_URL, BUY_SELL, BUY_SELL_URL } from '@/constants';
import { api } from '@/hooks';
import {
useGetBusinessHours,
useGetPhoneNumberVerification,
useIsAdvertiser,
useIsAdvertiserBarred,
useModalManager,
Expand All @@ -29,6 +30,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
const isBuySellPage = getCurrentRoute() === 'buy-sell';
const isAdvertiserBarred = useIsAdvertiserBarred();
const isAdvertiser = useIsAdvertiser();
const { shouldShowVerification } = useGetPhoneNumberVerification();
const { data } = api.advertiser.useGetInfo() || {};
const { data: poiPoaData } = usePoiPoaStatus();
const { isPoiPoaVerified } = poiPoaData || {};
Expand Down Expand Up @@ -91,11 +93,16 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {

const redirectToVerification = () => {
const searchParams = new URLSearchParams(location.search);
searchParams.set('poi_poa_verified', 'false');
history.replace({
pathname: location.pathname,
search: searchParams.toString(),
});
searchParams.set('verified', 'false');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the param name to make it more general since now we're also checking for PNV if enabled

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a question. why do we keep this in the URL params? I mean it can be easily manipulated by the user.
can we add a hook and check this in component level using that hook? 🤔


if (!isBuySellPage) {
history.push(`${BUY_SELL_URL}?${searchParams.toString()}`);
} else {
history.replace({
pathname: location.pathname,
search: searchParams.toString(),
});
}
};

const redirectToAdvertiser = () => {
Expand Down Expand Up @@ -263,7 +270,7 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
className='lg:min-w-[7.5rem]'
disabled={isAdvertiserBarred || !isScheduleAvailable}
onClick={() => {
if (!isAdvertiser && !isPoiPoaVerified) {
if (!isAdvertiser && (!isPoiPoaVerified || shouldShowVerification)) {
redirectToVerification();
} else {
setSelectedAdvertId(advertId);
Expand Down
13 changes: 12 additions & 1 deletion src/components/Checklist/Checklist.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
cursor: not-allowed;
}

&--done {
cursor: default;
background-color: #4bb4b3 !important;
}

&-icon {
fill: #fff;
}
Expand All @@ -50,8 +55,14 @@
@include icon-wrapper;

&-icon {
fill: #4bb4b3;
fill: #fff;
}
}

&-text {
display: flex;
flex-direction: column;
width: 100%;
}
}
}
56 changes: 38 additions & 18 deletions src/components/Checklist/Checklist.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,63 @@
import clsx from 'clsx';
import { LabelPairedArrowRightLgBoldIcon, LabelPairedCheckMdBoldIcon } from '@deriv/quill-icons';
import { Button, Text, useDevice } from '@deriv-com/ui';
import './Checklist.scss';

type TChecklistItem = {
isDisabled?: boolean;
onClick?: () => void;
phoneNumber?: string | null;
status: string;
testId?: string;
text: string;
};

const Checklist = ({ items }: { items: TChecklistItem[] }) => {
const { isMobile } = useDevice();

const getTextColor = (isDisabled: boolean | undefined, status: string) => {
if (isDisabled) return 'less-prominent';
if (status === 'rejected') return 'error';
return 'general';
};

return (
<div className='checklist'>
{items.map(item => (
<div className='checklist__item' key={item.text}>
<Text color={item.isDisabled ? 'less-prominent' : 'general'} size={isMobile ? 'md' : 'sm'}>
{item.text}
</Text>
{item.status === 'done' ? (
<div className='checklist__item-checkmark'>
<LabelPairedCheckMdBoldIcon className='checklist__item-checkmark-icon' />
{items.map(item => {
const isDone = item.status === 'done';

return (
<div className='checklist__item' key={item.text}>
<div className='checklist__item-text'>
<Text color={getTextColor(item.isDisabled, item.status)} size={isMobile ? 'md' : 'sm'}>
{item.text}
</Text>
{item.phoneNumber && (
<Text color='less-prominent' size={isMobile ? 'sm' : 'xs'}>
{item.phoneNumber}
</Text>
)}
</div>
) : (
<Button
className='checklist__item-button'
className={clsx('checklist__item-button', {
'checklist__item-button--done': isDone,
})}
disabled={item.isDisabled}
icon={
<LabelPairedArrowRightLgBoldIcon
className='checklist__item-button-icon'
{...(item.testId && { 'data-testid': item.testId })}
/>
isDone ? (
<LabelPairedCheckMdBoldIcon className='checklist__item-checkmark-icon' />
) : (
<LabelPairedArrowRightLgBoldIcon
className='checklist__item-button-icon'
{...(item.testId && { 'data-testid': item.testId })}
/>
)
}
onClick={item.onClick}
onClick={isDone ? undefined : item.onClick}
/>
)}
</div>
))}
</div>
);
})}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ const BlockUnblockUserModal = ({
};

const blockUnblockError = errorMessages.find(
error => error.code === ERROR_CODES.PERMISSION_DENIED || error.code === ERROR_CODES.INVALID_ADVERTISER_ID
error =>
error.code === ERROR_CODES.PERMISSION_DENIED ||
error.code === ERROR_CODES.INVALID_ADVERTISER_ID ||
error.code === ERROR_CODES.ADVERTISER_NOT_REGISTERED
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check for this edge case when user is not verified

Screenshot 2024-11-08 at 3 58 53 PM

);

if (blockUnblockError && isModalOpenFor('ErrorModal')) {
Expand Down
38 changes: 29 additions & 9 deletions src/components/Verification/Verification.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TLocalize } from 'types';
import { Checklist } from '@/components';
import { usePoiPoaStatus } from '@/hooks/custom-hooks';
import { useGetPhoneNumberVerification, usePoiPoaStatus } from '@/hooks/custom-hooks';
import { DerivLightIcCashierSendEmailIcon } from '@deriv/quill-icons';
import { Localize, useTranslations } from '@deriv-com/translations';
import { Loader, Text, useDevice } from '@deriv-com/ui';
Expand All @@ -14,9 +14,9 @@ const getPoiAction = (status: string | undefined, localize: TLocalize) => {
case 'rejected':
return localize('Identity verification failed. Please try again.');
case 'verified':
return localize('Identity verification complete.');
return localize('Identity verified');
default:
return localize('Upload documents to verify your identity.');
return localize('Your identity');
}
};

Expand All @@ -32,15 +32,22 @@ const getPoaAction = (
return localize('Address verification failed. Please try again.');
case 'verified':
if (isPoaAuthenticatedWithIdv) return localize('Upload documents to verify your address.');
return localize('Address verification complete.');
return localize('Address verified');
default:
return localize('Upload documents to verify your address.');
return localize('Your address');
}
};

const getStatus = (status: string | undefined) => {
if (status === 'verified') return 'done';
else if (status === 'rejected') return 'rejected';
return 'action';
};

const Verification = () => {
const { isMobile } = useDevice();
const { localize } = useTranslations();
const { isPhoneNumberVerificationEnabled, isPhoneNumberVerified, phoneNumber } = useGetPhoneNumberVerification();
const { data, isLoading } = usePoiPoaStatus();
const {
isP2PPoaRequired,
Expand Down Expand Up @@ -69,13 +76,26 @@ const Verification = () => {
};

const checklistItems = [
...(isPhoneNumberVerificationEnabled
? [
{
onClick: () => {
window.location.href = `${URLConstants.derivAppProduction}/account/personal-details`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do the redirection based on the environment.. if test link or staging, redirect to staging-app.deriv. else app.deriv ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmmm i dont think its necessary tbh, because either way we can still test the PNV using just prod link. Also even if we use staging and so forth, QA still need to set up the endpoint again

},
phoneNumber: isPhoneNumberVerified ? phoneNumber : undefined,
status: isPhoneNumberVerified ? 'done' : 'action',
testId: 'dt_verification_phone_number_arrow_button',
text: isPhoneNumberVerified ? localize('Phone number verified') : localize('Your phone number'),
},
]
: []),
{
isDisabled: isPoiPending,
onClick: () => {
if (!isPoiVerified)
redirectToVerification(`${URLConstants.derivAppProduction}/account/proof-of-identity`);
},
status: isPoiVerified ? 'done' : 'action',
status: getStatus(poiStatus),
testId: 'dt_verification_poi_arrow_button',
text: getPoiAction(poiStatus, localize),
},
Expand All @@ -87,7 +107,7 @@ const Verification = () => {
if (allowPoaRedirection)
redirectToVerification(`${URLConstants.derivAppProduction}/account/proof-of-address`);
},
status: allowPoaRedirection ? 'action' : 'done',
status: getStatus(poaStatus),
testId: 'dt_verification_poa_arrow_button',
text: getPoaAction(isPoaAuthenticatedWithIdv, poaStatus, localize),
},
Expand All @@ -101,10 +121,10 @@ const Verification = () => {
<div className='verification'>
<DerivLightIcCashierSendEmailIcon className='verification__icon' height={128} width={128} />
<Text className='verification__text' size={isMobile ? 'lg' : 'md'} weight='bold'>
<Localize i18n_default_text='Verify your P2P account' />
<Localize i18n_default_text='Let’s get you secured' />
</Text>
<Text align='center' className='verification__text' size={isMobile ? 'lg' : 'sm'}>
<Localize i18n_default_text='Verify your identity and address to use Deriv P2P.' />
<Localize i18n_default_text='Complete your P2P profile to enjoy secure transactions.' />
</Text>
<Checklist items={checklistItems} />
</div>
Expand Down
Loading
Loading