Topbar shows nagging verify-email modal after every page change

This commit is contained in:
Vesa Luusua 2017-09-13 20:38:06 +03:00
parent 3fe8a58c16
commit 9acae53053
2 changed files with 108 additions and 5 deletions

View file

@ -3,12 +3,13 @@ import { compose } from 'redux';
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
import { pickBy } from 'lodash';
import classNames from 'classnames';
import { Button, Modal, NamedLink, TopbarDesktop, TopbarMobileMenu } from '../../components';
import { TopbarSearchForm } from '../../containers';
import { ensureCurrentUser } from '../../util/data';
import { withFlattenedRoutes, withViewport } from '../../util/contextHelpers';
import { parse, stringify } from '../../util/urlHelpers';
import { createResourceLocatorString, pathByRouteName } from '../../util/routes';
import * as propTypes from '../../util/propTypes';
import { Button, Modal, NamedLink, TopbarDesktop, TopbarMobileMenu } from '../../components';
import { TopbarSearchForm } from '../../containers';
import MenuIcon from './MenuIcon';
import LogoIcon from './LogoIcon';
@ -38,6 +39,9 @@ const redirectToURLWithoutModalState = (props, modalStateParam) => {
class TopbarComponent extends Component {
constructor(props) {
super(props);
this.state = { showVerifyEmailReminder: false, hasSeenEmailReminder: false };
this.onHistoryChanged = this.handleEmailReminder.bind(this);
this.handleMobileMenuOpen = this.handleMobileMenuOpen.bind(this);
this.handleMobileMenuClose = this.handleMobileMenuClose.bind(this);
this.handleMobileSearchOpen = this.handleMobileSearchOpen.bind(this);
@ -46,6 +50,32 @@ class TopbarComponent extends Component {
this.handleLogout = this.handleLogout.bind(this);
}
componentWillReceiveProps(nextProps) {
const { currentUser, currentUserHasListings, currentUserHasOrders, location } = nextProps;
const user = ensureCurrentUser(currentUser);
// Track if path changes inside Page level component
const pathChanged = location.pathname !== this.props.location.pathname;
this.handleEmailReminder(user, currentUserHasListings, currentUserHasOrders, pathChanged);
}
handleEmailReminder(currentUser, currentUserHasListings, currentUserHasOrders, pathChanged) {
const emailUnverified = currentUser.id && !currentUser.attributes.emailVerified;
const notRemindedYet = !this.state.showVerifyEmailReminder && !this.state.hasSeenEmailReminder;
const showOnPathChange = notRemindedYet || pathChanged;
// Emails are sent when order is initiated
// Customer is likely to get email soon when she books something
// Provider email should work - she should get an email when someone books a listing
const hasOrders = currentUserHasOrders === true;
const hasListingsOrOrders = currentUserHasListings || hasOrders;
// Show reminder
if (emailUnverified && hasListingsOrOrders && showOnPathChange) {
this.setState({ showVerifyEmailReminder: true });
}
}
handleMobileMenuOpen() {
redirectToURLWithModalState(this.props, 'mobilemenu');
}
@ -191,6 +221,16 @@ class TopbarComponent extends Component {
</p>
</div>
</Modal>
<Modal
id="EmailVerificationReminder"
isOpen={this.state.showVerifyEmailReminder}
onClose={() => {
this.setState({ showVerifyEmailReminder: false, hasSeenEmailReminder: true });
}}
onManageDisableScrolling={onManageDisableScrolling}
>
<div style={{ width: '400px', height: '400px' }}>Nag nag naggity nag</div>
</Modal>
</div>
);
}
@ -202,6 +242,7 @@ TopbarComponent.defaultProps = {
mobileRootClassName: null,
notificationCount: 0,
currentUser: null,
currentUserHasOrders: null,
currentPage: null,
};
@ -215,6 +256,7 @@ TopbarComponent.propTypes = {
authInProgress: bool.isRequired,
currentUser: propTypes.currentUser,
currentUserHasListings: bool.isRequired,
currentUserHasOrders: bool,
currentPage: string,
notificationCount: number,
onLogout: func.isRequired,

View file

@ -21,6 +21,10 @@ export const FETCH_CURRENT_USER_NOTIFICATIONS_REQUEST = 'app/user/FETCH_CURRENT_
export const FETCH_CURRENT_USER_NOTIFICATIONS_SUCCESS = 'app/user/FETCH_CURRENT_USER_NOTIFICATIONS_SUCCESS';
export const FETCH_CURRENT_USER_NOTIFICATIONS_ERROR = 'app/user/FETCH_CURRENT_USER_NOTIFICATIONS_ERROR';
export const FETCH_CURRENT_USER_HAS_ORDERS_REQUEST = 'app/user/FETCH_CURRENT_USER_HAS_ORDERS_REQUEST';
export const FETCH_CURRENT_USER_HAS_ORDERS_SUCCESS = 'app/user/FETCH_CURRENT_USER_HAS_ORDERS_SUCCESS';
export const FETCH_CURRENT_USER_HAS_ORDERS_ERROR = 'app/user/FETCH_CURRENT_USER_HAS_ORDERS_ERROR';
export const SEND_VERIFICATION_EMAIL_REQUEST = 'app/user/SEND_VERIFICATION_EMAIL_REQUEST';
export const SEND_VERIFICATION_EMAIL_SUCCESS = 'app/user/SEND_VERIFICATION_EMAIL_SUCCESS';
export const SEND_VERIFICATION_EMAIL_ERROR = 'app/user/SEND_VERIFICATION_EMAIL_ERROR';
@ -36,6 +40,8 @@ const initialState = {
currentUserHasListingsError: null,
currentUserNotificationCount: 0,
currentUserNotificationCountError: null,
currentUserHasOrders: null, // This is not fetched unless unverified emails exist
currentUserHasOrdersError: null,
sendVerificationEmailInProgress: false,
sendVerificationEmailError: null,
};
@ -79,6 +85,14 @@ export default function reducer(state = initialState, action = {}) {
console.error(payload); // eslint-disable-line
return { ...state, currentUserNotificationCountError: payload };
case FETCH_CURRENT_USER_HAS_ORDERS_REQUEST:
return { ...state, currentUserHasOrdersError: null };
case FETCH_CURRENT_USER_HAS_ORDERS_SUCCESS:
return { ...state, currentUserHasOrders: payload.hasOrders };
case FETCH_CURRENT_USER_HAS_ORDERS_ERROR:
console.error(payload); // eslint-disable-line
return { ...state, currentUserHasOrdersError: payload };
case STRIPE_ACCOUNT_CREATE_REQUEST:
return { ...state, createStripeAccountError: null, createStripeAccountInProgress: true };
case STRIPE_ACCOUNT_CREATE_SUCCESS:
@ -177,6 +191,21 @@ const fetchCurrentUserNotificationsError = e => ({
payload: e,
});
const fetchCurrentUserHasOrdersRequest = () => ({
type: FETCH_CURRENT_USER_HAS_ORDERS_REQUEST,
});
export const fetchCurrentUserHasOrdersSuccess = hasOrders => ({
type: FETCH_CURRENT_USER_HAS_ORDERS_SUCCESS,
payload: { hasOrders },
});
const fetchCurrentUserHasOrdersError = e => ({
type: FETCH_CURRENT_USER_HAS_ORDERS_ERROR,
error: true,
payload: e,
});
export const sendVerificationEmailRequest = () => ({
type: SEND_VERIFICATION_EMAIL_REQUEST,
});
@ -220,11 +249,38 @@ export const fetchCurrentUserHasListings = () =>
dispatch(fetchCurrentUserHasListingsSuccess(!!hasListings));
})
.catch(e => {
// TODO: dispatch flash message
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
dispatch(fetchCurrentUserHasListingsError(e));
});
};
export const fetchCurrentUserHasOrders = () =>
(dispatch, getState, sdk) => {
dispatch(fetchCurrentUserHasOrdersRequest());
if (!getState().user.currentUser) {
dispatch(fetchCurrentUserHasOrdersSuccess(false));
return Promise.resolve(null);
}
const params = {
only: 'order',
page: 1,
per_page: 1,
};
return sdk.transactions
.query(params)
.then(response => {
const hasOrders = response.data.data && response.data.data.length > 0;
dispatch(fetchCurrentUserHasOrdersSuccess(!!hasOrders));
})
.catch(e => {
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
dispatch(fetchCurrentUserHasOrdersError(e));
});
};
// Notificaiton page size is max (100 items on page)
const NOTIFICATION_PAGE_SIZE = 100;
@ -246,6 +302,7 @@ export const fetchCurrentUserNotifications = () =>
dispatch(fetchCurrentUserNotificationsSuccess(transactions));
})
.catch(e => {
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
dispatch(fetchCurrentUserNotificationsError(e));
throw e;
});
@ -271,13 +328,17 @@ export const fetchCurrentUser = () =>
const denormalised = denormalisedEntities(entities, 'current-user', [currentUserId]);
const currentUser = denormalised[0];
dispatch(currentUserShowSuccess(currentUser));
return currentUser;
})
.then(() => {
.then(currentUser => {
dispatch(fetchCurrentUserHasListings());
dispatch(fetchCurrentUserNotifications());
if (!currentUser.attributes.emailVerified) {
dispatch(fetchCurrentUserHasOrders());
}
})
.catch(e => {
// TODO: dispatch flash message
// TODO: dispatch flash message: "Something went wrong while retrieving user info"
dispatch(currentUserShowError(e));
});
};