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

Tw 716 baner subscrition #918

Merged
merged 15 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 14 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
6 changes: 6 additions & 0 deletions e2e/src/features/create-new-wallet.feature
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@ Feature: Create a new wallet
And I press Accept Terms Checkbox on the Register Form page
And I press Create Button on the Register Form page

And I am on the OnRumpModal page
And I press Close Button on the On-ramp Modal page

And I am on the NewsletterModal page
And I press Close Button on the Newsletter Modal page

Then I am on the Home page

3 changes: 3 additions & 0 deletions e2e/src/features/import-existing-wallet.feature
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ Feature: Import existing wallet
And I press Accept Terms Checkbox on the Register Form page
And I press Import Button on the Register Form page

And I am on the NewsletterModal page
And I press Close Button on the Newsletter Modal page

Then I am on the Home page

7 changes: 6 additions & 1 deletion e2e/src/page-objects/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { NetworksDropDown } from 'e2e/src/page-objects/pages/drop-down-lists/networks.drop-down';
import { SwapPage } from 'e2e/src/page-objects/pages/swap.page';

import { NetworksDropDown } from 'e2e/src/page-objects/pages/drop-down-lists/networks.drop-down';
import { NewsletterModalPage } from 'e2e/src/page-objects/pages/newsletter-modal.page';
import { OnRumModalPage } from 'e2e/src/page-objects/pages/on-rum-modal.page';

import { OperationStatusAlert } from './pages/alerts/operation-status.alert';
import { CreateOrRestoreAnAccountPage } from './pages/create-or-restore-an-account.page';
import { DelegateFormPage } from './pages/delegate-form.page';
Expand Down Expand Up @@ -47,5 +50,7 @@ export const Pages = {
OperationStatusAlert: new OperationStatusAlert(),
Send: new SendPage(),
NetworksDropDown: new NetworksDropDown(),
OnRumpModal: new OnRumModalPage(),
NewsletterModal: new NewsletterModalPage(),
Swap: new SwapPage()
};
16 changes: 16 additions & 0 deletions e2e/src/page-objects/pages/newsletter-modal.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NewsletterOverlaySelectors } from 'src/app/layouts/PageLayout/NewsletterOverlay/NewsletterOverlay.selectors';

import { Page } from '../../classes/page.class';
import { createPageElement } from '../../utils/search.utils';

export class NewsletterModalPage extends Page {
closeButton = createPageElement(NewsletterOverlaySelectors.closeButton);
emailInput = createPageElement(NewsletterOverlaySelectors.emailInput);
subscribeButton = createPageElement(NewsletterOverlaySelectors.subscribeButton);

async isVisible() {
await this.closeButton.waitForDisplayed();
await this.emailInput.waitForDisplayed();
await this.subscribeButton.waitForDisplayed();
}
}
20 changes: 20 additions & 0 deletions e2e/src/page-objects/pages/on-rum-modal.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { OnRampOverlaySelectors } from 'src/app/layouts/PageLayout/OnRampOverlay/OnRampOverlay.selectors';

import { Page } from '../../classes/page.class';
import { createPageElement } from '../../utils/search.utils';

export class OnRumModalPage extends Page {
closeButton = createPageElement(OnRampOverlaySelectors.closeButton);
fiftyDollarButton = createPageElement(OnRampOverlaySelectors.fiftyDollarButton);
oneHundredDollarButton = createPageElement(OnRampOverlaySelectors.oneHundredDollarButton);
twoHundredDollarButton = createPageElement(OnRampOverlaySelectors.twoHundredDollarButton);
customAmountButton = createPageElement(OnRampOverlaySelectors.customAmountButton);

async isVisible() {
await this.closeButton.waitForDisplayed();
await this.fiftyDollarButton.waitForDisplayed();
await this.oneHundredDollarButton.waitForDisplayed();
await this.twoHundredDollarButton.waitForDisplayed();
await this.customAmountButton.waitForDisplayed();
}
}
3 changes: 3 additions & 0 deletions e2e/src/step-definitions/common.steps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@ Given(/I have imported an existing account/, { timeout: LONG_TIMEOUT }, async ()
await Pages.SetWallet.acceptTerms.click();
await Pages.SetWallet.importButton.click();

await Pages.NewsletterModal.isVisible();
await Pages.NewsletterModal.closeButton.click();

await Pages.Home.isVisible();
});
6 changes: 6 additions & 0 deletions public/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3032,5 +3032,11 @@
},
"creditCard": {
"message": "credit card"
},
"subscribeToNewsletter": {
"message": "Subscribe to our Newsletter"
},
"keepLatestNews": {
"message": "Keep up with the latest news from Madfish"
}
}
6 changes: 6 additions & 0 deletions public/_locales/en_GB/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1773,5 +1773,11 @@
},
"swapCashbackDescription": {
"message": "Swap more than 10$ and receive 0.175% from the swapped amount in the TKEY token as a cashback"
},
"subscribeToNewsletter": {
"message": "Subscribe to our Newsletter"
},
"keepLatestNews": {
"message": "Keep up with the latest news from Madfish"
}
}
2 changes: 2 additions & 0 deletions src/app/layouts/PageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { PageLayoutSelectors } from './PageLayout.selectors';
import { ChangelogOverlay } from './PageLayout/ChangelogOverlay/ChangelogOverlay';
import ConfirmationOverlay from './PageLayout/ConfirmationOverlay';
import Header from './PageLayout/Header';
import { NewsletterOverlay } from './PageLayout/NewsletterOverlay/NewsletterOverlay';
import { OnRampOverlay } from './PageLayout/OnRampOverlay/OnRampOverlay';

interface PageLayoutProps extends PropsWithChildren, ToolbarProps {
Expand Down Expand Up @@ -52,6 +53,7 @@ const PageLayout: FC<PageLayoutProps> = ({ children, contentContainerStyle, ...t
<ConfirmationOverlay />
<ChangelogOverlay />
<OnRampOverlay />
<NewsletterOverlay />
</>
);
};
Expand Down
herkoss marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum NewsletterOverlaySelectors {
closeButton = 'Newsletter Modal/Close Button',
emailInput = 'Newsletter Modal/Email Input',
subscribeButton = 'Newsletter Modal/Subscribe Button'
}
160 changes: 160 additions & 0 deletions src/app/layouts/PageLayout/NewsletterOverlay/NewsletterOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import React, { FC, useMemo, useState } from 'react';

import classNames from 'clsx';
import { useForm } from 'react-hook-form';
import { useDispatch } from 'react-redux';
import { object, string } from 'yup';

import { Button } from 'app/atoms';
import Spinner from 'app/atoms/Spinner/Spinner';
import { useAppEnv } from 'app/env';
import { ReactComponent as CloseIcon } from 'app/icons/close.svg';
import ContentContainer from 'app/layouts/ContentContainer';
import { useOnboardingProgress } from 'app/pages/Onboarding/hooks/useOnboardingProgress.hook';
import { shouldShowNewsletterModalAction } from 'app/store/newsletter/newsletter-actions';
import { useShouldShowNewsletterModalSelector } from 'app/store/newsletter/newsletter-selectors';
import { useOnRampPossibilitySelector } from 'app/store/settings/selectors';
import { newsletterApi } from 'lib/apis/newsletter';
import { useYupValidationResolver } from 'lib/form/use-yup-validation-resolver';
import { T, t } from 'lib/i18n/react';
import { useLocation } from 'lib/woozie';

import { setTestID } from '../../../../lib/analytics';
import NewsletterImage from './NewsletterImage.png';
import { NewsletterOverlaySelectors } from './NewsletterOverlay.selectors';

interface FormValues {
email: string;
}

const validationSchema = object().shape({
email: string().required('Required field').email('Must be a valid email')
});

const HOME_PAGE_PATH = '/';

export const NewsletterOverlay: FC = () => {
const dispatch = useDispatch();
const { popup } = useAppEnv();
const { pathname } = useLocation();

const { onboardingCompleted } = useOnboardingProgress();
const shouldShowNewsletterModal = useShouldShowNewsletterModalSelector();
const isOnRampPossibility = useOnRampPossibilitySelector();

const validationResolver = useYupValidationResolver<FormValues>(validationSchema);

const { errors, handleSubmit, watch, register } = useForm<FormValues>({
defaultValues: { email: '' },
validationResolver
});
const email = watch('email');
const isValid = Object.keys(errors).length === 0;

const [isLoading, setIsLoading] = useState(false);
const [successSubscribing, setSuccessSubscribing] = useState(false);

const popupClassName = useMemo(
() => (popup ? 'inset-0 p-4' : 'top-1/2 left-1/2 transform -translate-y-1/2 -translate-x-1/2'),
[popup]
);
const closeButtonClassName = useMemo(() => (popup ? 'top-8 right-8' : 'top-4 right-4'), [popup]);
const close = () => void dispatch(shouldShowNewsletterModalAction(false));

const onSubmit = () => {
setIsLoading(true);
newsletterApi
.post('/', {
NAME: email,
EMAIL: email
})
.then(() => {
setSuccessSubscribing(true);
dispatch(shouldShowNewsletterModalAction(false));
})
.finally(() => setIsLoading(false));
};

const buttonContent = useMemo(() => {
if (successSubscribing) {
return 'Thanks for your subscribing!';
}

if (isLoading) {
return <Spinner theme="white" className="w-8" />;
}

return 'Subscribe';
}, [successSubscribing, isLoading]);

if (!shouldShowNewsletterModal || !onboardingCompleted || isOnRampPossibility || pathname !== HOME_PAGE_PATH)
return null;

return (
<>
<div className="fixed left-0 right-0 top-0 bottom-0 opacity-20 bg-gray-700 z-40"></div>
<form onSubmit={handleSubmit(onSubmit)}>
<ContentContainer
className={classNames('fixed z-40 overflow-y-scroll', popupClassName)}
style={{ maxWidth: '37.5rem', maxHeight: 'calc(100vh - 50px)' }}
padding={false}
>
<div
className={classNames(
'flex flex-col justify-center text-center bg-orange-100 shadow-lg bg-no-repeat rounded-md',
popup ? 'h-full' : 'h-700',
popup ? 'p-4' : 'px-3.5 py-4.5'
)}
>
<Button
className={classNames(
'absolute w-24 h-9 uppercase bg-blue-500',
'font-inter text-white',
'text-sm font-medium rounded',
'flex flex-row justify-center items-center self-end',
'hover:opacity-90',
closeButtonClassName
)}
onClick={close}
testID={NewsletterOverlaySelectors.closeButton}
>
<T id="close" />
<CloseIcon className="ml-2 h-4 w-auto stroke-current stroke-2" />
</Button>
<img
src={NewsletterImage}
style={{ maxHeight: '375px', maxWidth: '496px' }}
className="mb-4"
alt="Newsletter"
/>
<div className="flex flex-col w-full max-w-sm mx-auto">
<h1 className="mb-1 font-inter text-base text-gray-910 text-left">{t('subscribeToNewsletter')}</h1>
<span className="mb-1 text-xs text-left text-gray-600">{t('keepLatestNews')}</span>
<div className="w-full mb-4">
<input
ref={register()}
name="email"
className="w-full max-h-3/25 p-4 rounded-md border text-sm text-gray-910"
placeholder="example@mail.com"
{...setTestID(NewsletterOverlaySelectors.emailInput)}
/>
{!isValid && <div className="mt-1 text-xs text-left text-red-700">{errors.email?.message}</div>}
</div>
<button
disabled={!isValid}
type="submit"
className={classNames(
'w-full h-12 flex items-center justify-center font-semibold rounded-md text-base px-16 py-3 text-white',
isValid ? 'bg-orange-500' : 'bg-blue-100'
)}
{...setTestID(NewsletterOverlaySelectors.subscribeButton)}
>
{buttonContent}
</button>
</div>
</div>
</ContentContainer>
</form>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
specialCharacterRegx,
uppercaseLowercaseMixtureRegx
} from 'app/defaults';
import { shouldShowNewsletterModalAction } from 'app/store/newsletter/newsletter-actions';
import { setIsAnalyticsEnabledAction, setOnRampPossibilityAction } from 'app/store/settings/actions';
import { AnalyticsEventCategory, TestIDProps, useAnalytics } from 'lib/analytics';
import { T, t } from 'lib/i18n';
Expand Down Expand Up @@ -118,6 +119,7 @@ export const SetWalletPassword: FC<SetWalletPasswordProps> = ({
);
navigate('/loading');
!ownMnemonic && dispatch(setOnRampPossibilityAction(true));
dispatch(shouldShowNewsletterModalAction(true));
} catch (err: any) {
console.error(err);

Expand Down
4 changes: 3 additions & 1 deletion src/app/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { currencyEpics } from './currency/epics';
import { currencyReducer } from './currency/reducers';
import { dAppsEpics } from './d-apps/epics';
import { dAppsReducer } from './d-apps/reducers';
import { newsletterReducers } from './newsletter/newsletter-reducers';
import { partnersPromotionEpics } from './partners-promotion/epics';
import { partnersPromotionRucer } from './partners-promotion/reducers';
import { settingsReducer } from './settings/reducers';
Expand All @@ -37,7 +38,8 @@ const baseReducer = rootStateReducer({
balances: balancesReducer,
tokensMetadata: tokensMetadataReducer,
abTesting: abTestingReducer,
buyWithCreditCard: buyWithCreditCardReducer
buyWithCreditCard: buyWithCreditCardReducer,
newsletter: newsletterReducers
});

export type RootState = GetStateType<typeof baseReducer>;
Expand Down
3 changes: 3 additions & 0 deletions src/app/store/newsletter/newsletter-actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createAction } from '@reduxjs/toolkit';

export const shouldShowNewsletterModalAction = createAction<boolean>('newsletter/SHOULD_SHOW_NEWSLETTER_MODAL');
10 changes: 10 additions & 0 deletions src/app/store/newsletter/newsletter-reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createReducer } from '@reduxjs/toolkit';

import { shouldShowNewsletterModalAction } from './newsletter-actions';
import { NewsletterState, newsletterInitialState } from './newsletter-state';

export const newsletterReducers = createReducer<NewsletterState>(newsletterInitialState, builer => {
builer.addCase(shouldShowNewsletterModalAction, (_, { payload }) => ({
shouldShowNewsletterModal: payload
}));
});
4 changes: 4 additions & 0 deletions src/app/store/newsletter/newsletter-selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { useSelector } from '../index';

export const useShouldShowNewsletterModalSelector = () =>
useSelector(({ newsletter }) => newsletter.shouldShowNewsletterModal);
5 changes: 5 additions & 0 deletions src/app/store/newsletter/newsletter-state.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NewsletterState } from './newsletter-state';

export const mockNewsletterState: NewsletterState = {
shouldShowNewsletterModal: true
};
7 changes: 7 additions & 0 deletions src/app/store/newsletter/newsletter-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface NewsletterState {
shouldShowNewsletterModal: boolean;
}

export const newsletterInitialState: NewsletterState = {
shouldShowNewsletterModal: true
};
4 changes: 3 additions & 1 deletion src/app/store/root-state.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { mockBuyWithCreditCardState } from './buy-with-credit-card/state.mock';
import { mockCurrencyState } from './currency/state.mock';
import { mockDAppsState } from './d-apps/state.mock';
import { RootState } from './index';
import { mockNewsletterState } from './newsletter/newsletter-state.mock';
import { mockPartnersPromotionState } from './partners-promotion/state.mock';
import { mockSettingsState } from './settings/state.mock';
import { mockSwapState } from './swap/state.mock';
Expand All @@ -24,5 +25,6 @@ export const mockRootState: RootState = {
balances: mockBalancesState,
tokensMetadata: mockTokensMetadataState,
abTesting: mockABTestingState,
buyWithCreditCard: mockBuyWithCreditCardState
buyWithCreditCard: mockBuyWithCreditCardState,
newsletter: mockNewsletterState
};
5 changes: 5 additions & 0 deletions src/lib/apis/newsletter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import axios from 'axios';

export const newsletterApi = axios.create({
baseURL: 'https://jellyfish-app-deove.ondigitalocean.app/'
});
Loading