Skip to content

Commit

Permalink
Merge pull request #103 from suisin-deriv/suisin/pnv/notification_onc…
Browse files Browse the repository at this point in the history
…lick_scroll_to_phone_field

chore: refactor notification tray while onclick auto scroll to phone …
  • Loading branch information
suisin-deriv committed Aug 27, 2024
2 parents 0a4de06 + ab40f71 commit 41e3cf2
Show file tree
Hide file tree
Showing 35 changed files with 533 additions and 508 deletions.
2 changes: 1 addition & 1 deletion packages/account/src/Constants/routes-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const initRoutesConfig = () => [
{
path: routes.phone_verification,
component: PhoneVerificationPage,
getTitle: () => localize('Personal details'),
getTitle: () => localize('Phone number verification'),
is_hidden: true,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ describe('<PersonalDetailsForm />', () => {
renderComponent();
expect(screen.queryByText(/Loading/)).not.toBeInTheDocument();
await waitFor(() => {
expect(
screen.getByText(
/Please make sure your information is correct or it may affect your trading experience./i
)
).toBeInTheDocument();
expect(screen.getByText(/Ensure your information is correct./i)).toBeInTheDocument();
});
});

Expand Down Expand Up @@ -185,14 +181,14 @@ describe('<PersonalDetailsForm />', () => {
).toBeInTheDocument();
});

it('should update user profile after clicking on submit', () => {
it('should update user profile after clicking on Save changes', () => {
renderComponent();
const first_name = screen.getByTestId('dt_first_name') as HTMLInputElement;
expect(first_name.value).toBe('John');
userEvent.clear(first_name);
userEvent.type(first_name, 'James');
const submit_button = screen.getByRole('button', { name: /Submit/ });
userEvent.click(submit_button);
const save_changes_button = screen.getByRole('button', { name: /Save changes/ });
userEvent.click(save_changes_button);
expect(first_name.value).toBe('James');
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { VerifyButton } from '../verify-button';
import { StoreProvider, mockStore } from '@deriv/stores';
import { Router } from 'react-router';
import { createBrowserHistory } from 'history';
import { routes } from '@deriv/shared';
import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { usePhoneNumberVerificationSetTimer, useVerifyEmail } from '@deriv/hooks';
import { routes } from '@deriv/shared';
import { StoreProvider, mockStore } from '@deriv/stores';
import { VerifyButton } from '../verify-button';

jest.mock('@deriv/hooks', () => ({
...jest.requireActual('@deriv/hooks'),
Expand All @@ -31,27 +31,28 @@ describe('VerifyButton', () => {
},
},
});
let mock_next_email_otp_request_timer = 0;

const renderWithRouter = () => {
return render(
<Router history={history}>
<StoreProvider store={mock_store}>
<VerifyButton setIsPhoneFieldDisable={jest.fn()} />
<VerifyButton
is_verify_button_disabled={false}
next_email_otp_request_timer={mock_next_email_otp_request_timer}
/>
</StoreProvider>
</Router>
);
};

it('should render Verify Button', () => {
renderWithRouter();
expect(screen.getByText('Verify')).toBeInTheDocument();
beforeEach(() => {
mock_next_email_otp_request_timer = 0;
});

it('should render Verify Button with countdown timer return from usePhoneNumberSetTimer and should have disabled class', () => {
(usePhoneNumberVerificationSetTimer as jest.Mock).mockReturnValue({ next_otp_request: 'in 60s' });
it('should render Verify Button', () => {
renderWithRouter();
expect(screen.getByText('Verify in 60s')).toBeInTheDocument();
expect(screen.getByText('Verify in 60s')).toHaveClass('phone-verification-btn--not-verified--disabled');
expect(screen.getByText('Verify')).toBeInTheDocument();
});

it('should redirect user to phone-verification page when clicked on Verify Button', () => {
Expand All @@ -67,37 +68,17 @@ describe('VerifyButton', () => {
expect(history.location.pathname).toBe(routes.phone_verification);
});

it('should render Verified text', () => {
if (mock_store.client.account_settings.phone_number_verification)
mock_store.client.account_settings.phone_number_verification.verified = 1;
renderWithRouter();
expect(screen.getByText('Verified')).toBeInTheDocument();
expect(screen.getByTestId('dt_phone_verification_popover')).toBeInTheDocument();
});

it('should render popover text when popover is clicked', () => {
if (mock_store.client.account_settings.phone_number_verification)
mock_store.client.account_settings.phone_number_verification.verified = 1;
it('should render Verify Button with timer if next_otp_request has value', () => {
mock_next_email_otp_request_timer = 2;
renderWithRouter();
const popover = screen.getByTestId('dt_phone_verification_popover');
userEvent.click(popover);
expect(screen.getByText(/To change your verified phone number, contact us via/)).toBeInTheDocument();
expect(screen.getByText(/live chat/)).toBeInTheDocument();
expect(screen.getByText('Verify in 2s')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Verify in 2s' })).toBeDisabled();
});

it('should render live chat window when live chat is clicked', () => {
it('should render Verified text', () => {
if (mock_store.client.account_settings.phone_number_verification)
mock_store.client.account_settings.phone_number_verification.verified = 1;
window.LC_API = {
open_chat_window: jest.fn(),
on_chat_ended: jest.fn(),
};

renderWithRouter();
const popover = screen.getByTestId('dt_phone_verification_popover');
userEvent.click(popover);
const livechat = screen.getByText(/live chat/);
userEvent.click(livechat);
expect(window.LC_API.open_chat_window).toHaveBeenCalled();
expect(screen.getByText('Verified')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
HintBox,
Input,
Loading,
OpenLiveChatLink,
SelectNative,
Text,
} from '@deriv/components';
Expand All @@ -31,24 +32,33 @@ import { getPersonalDetailsInitialValues, getPersonalDetailsValidationSchema, ma
import FormSelectField from 'Components/forms/form-select-field';
import { VerifyButton } from './verify-button';
import { useInvalidateQuery } from '@deriv/api';
import { useStatesList, useResidenceList, useGrowthbookGetFeatureValue } from '@deriv/hooks';
import {
useStatesList,
useResidenceList,
useGrowthbookGetFeatureValue,
usePhoneNumberVerificationSetTimer,
} from '@deriv/hooks';

type TRestState = {
show_form: boolean;
api_error?: string;
};

type THintMessage = {
is_phone_number_editted: boolean;
};

const PersonalDetailsForm = observer(() => {
const { isDesktop } = useDevice();
const [is_loading, setIsLoading] = useState(false);
const [is_btn_loading, setIsBtnLoading] = useState(false);
const [is_submit_success, setIsSubmitSuccess] = useState(false);
const [is_phone_field_disable, setIsPhoneFieldDisable] = useState(false);
const invalidate = useInvalidateQuery();
const history = useHistory();
const [isPhoneNumberVerificationEnabled] = useGrowthbookGetFeatureValue({
featureFlag: 'phone_number_verification',
});
const { is_request_button_disabled, next_email_otp_request_timer } = usePhoneNumberVerificationSetTimer();

const {
client,
Expand Down Expand Up @@ -109,6 +119,29 @@ const PersonalDetailsForm = observer(() => {
}
}, [invalidate, is_language_changing]);

const hintMessage = ({ is_phone_number_editted }: THintMessage) => {
if (isPhoneNumberVerificationEnabled) {
if (account_settings?.phone_number_verification?.verified) {
return (
<Localize
i18n_default_text='To change your verified phone number, contact us via <0></0>.'
components={[
<OpenLiveChatLink
text_size='xxs'
key={0}
className='account-form__fieldset--phone-verification-livechat-link'
/>,
]}
/>
);
} else if (is_phone_number_editted) {
return <Localize i18n_default_text='Save changes to enable verification.' />;
}
} else {
return null;
}
};

const onSubmit = async (values: GetSettings, { setStatus, setSubmitting }: FormikHelpers<GetSettings>) => {
setStatus({ msg: '' });
const request = makeSettingsRequest({ ...values }, residence_list, states_list, is_virtual);
Expand Down Expand Up @@ -366,27 +399,36 @@ const PersonalDetailsForm = observer(() => {
name='phone'
id={'phone'}
label={localize('Phone number*')}
className={clsx({
'account-form__fieldset--phone':
account_settings?.phone_number_verification?.verified,
})}
//@ts-expect-error type of residence should not be null: needs to be updated in GetSettings type
value={values.phone}
hint={hintMessage({
is_phone_number_editted: account_settings.phone !== values.phone,
})}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
handleChange(e);
setStatus('');
}}
onBlur={handleBlur}
required
error={errors.phone}
disabled={isFieldDisabled('phone') || is_phone_field_disable}
disabled={
isFieldDisabled('phone') ||
is_request_button_disabled ||
!!next_email_otp_request_timer
}
data-testid='dt_phone'
/>
{isPhoneNumberVerificationEnabled &&
account_settings.phone &&
account_settings.phone === values.phone && (
<VerifyButton setIsPhoneFieldDisable={setIsPhoneFieldDisable} />
)}
{isPhoneNumberVerificationEnabled && (
<VerifyButton
is_verify_button_disabled={
isFieldDisabled('phone') ||
is_request_button_disabled ||
account_settings.phone !== values.phone ||
!account_settings.phone
}
next_email_otp_request_timer={next_email_otp_request_timer}
/>
)}
</fieldset>
)}
<Fragment>
Expand Down Expand Up @@ -668,9 +710,7 @@ const PersonalDetailsForm = observer(() => {
color='prominent'
align={isDesktop ? 'right' : 'center'}
>
{localize(
'Please make sure your information is correct or it may affect your trading experience.'
)}
<Localize i18n_default_text='Ensure your information is correct.' />
</Text>
)}
<Button
Expand All @@ -684,7 +724,7 @@ const PersonalDetailsForm = observer(() => {
has_effect
is_loading={is_btn_loading}
is_submit_success={is_submit_success}
text={localize('Submit')}
text={localize('Save changes')}
large
primary
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,7 @@
.phone-verification-btn {
.phone-verification-button {
position: absolute;
inset-inline-end: 0;
top: 0.4rem;

&--not-verified {
display: flex;
padding-top: 0.6rem;
padding-inline-end: 1.2rem;
cursor: pointer;

&--disabled {
cursor: not-allowed;
color: rgba(#ff444f, 0.5);
}
}

&--verified {
display: flex;
padding-top: 0.6rem;
padding-inline-end: 1.2rem;
color: var(--text-profit-success);

@include mobile-or-tablet-screen {
padding-inline-end: 4rem;
}

> :first-child {
padding-inline-end: 0.4rem;
}

.phone-verification__popover {
position: absolute;
inset-inline-end: -3rem;

@include mobile-or-tablet-screen {
inset-inline-end: 0rem;
}
}
}
top: 0;
border-end-start-radius: 0;
border-start-start-radius: 0;
}
Loading

0 comments on commit 41e3cf2

Please sign in to comment.