mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 03:43:28 +10:00
Merge pull request #846 from sharetribe/extract-missing-information-modal
Extract missing information modal
This commit is contained in:
commit
f362e585df
8 changed files with 311 additions and 191 deletions
|
|
@ -12,9 +12,14 @@ way to update this template, but currently, we follow a pattern:
|
|||
|
||||
---
|
||||
|
||||
## Upcoming version
|
||||
|
||||
* [fix] Extract and fix missing information reminder modal from Topbar
|
||||
[#846](https://github.com/sharetribe/flex-template-web/pull/846)
|
||||
|
||||
## v0.3.1
|
||||
|
||||
* Change lodash import syntax to reduce bundle size (-15.14 KB)
|
||||
* [change] Change lodash import syntax to reduce bundle size (-15.14 KB)
|
||||
[#839](https://github.com/sharetribe/flex-template-web/pull/839)
|
||||
* [fix] Use https instead of git to access SDK repo for Heroku build (now that the repo is public).
|
||||
TODO: create SDK releases instead of using direct refs to single commit.
|
||||
|
|
|
|||
75
src/components/ModalMissingInformation/EmailReminder.js
Normal file
75
src/components/ModalMissingInformation/EmailReminder.js
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { isTooManyEmailVerificationRequestsError } from '../../util/errors';
|
||||
import { IconEmailAttention, InlineTextButton, NamedLink } from '../../components';
|
||||
|
||||
import css from './ModalMissingInformation.css';
|
||||
|
||||
const EmailReminder = props => {
|
||||
const {
|
||||
className,
|
||||
user,
|
||||
sendVerificationEmailInProgress,
|
||||
sendVerificationEmailError,
|
||||
onResendVerificationEmail,
|
||||
} = props;
|
||||
|
||||
const email = user.id ? <span className={css.email}>{user.attributes.email}</span> : '';
|
||||
|
||||
const resendEmailLink = (
|
||||
<InlineTextButton className={css.helperLink} onClick={onResendVerificationEmail}>
|
||||
<FormattedMessage id="ModalMissingInformation.resendEmailLinkText" />
|
||||
</InlineTextButton>
|
||||
);
|
||||
|
||||
const fixEmailLink = (
|
||||
<NamedLink className={css.helperLink} name="ContactDetailsPage">
|
||||
<FormattedMessage id="ModalMissingInformation.fixEmailLinkText" />
|
||||
</NamedLink>
|
||||
);
|
||||
|
||||
const resendErrorTranslationId = isTooManyEmailVerificationRequestsError(
|
||||
sendVerificationEmailError
|
||||
)
|
||||
? 'ModalMissingInformation.resendFailedTooManyRequests'
|
||||
: 'ModalMissingInformation.resendFailed';
|
||||
const resendErrorMessage = sendVerificationEmailError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id={resendErrorTranslationId} />
|
||||
</p>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<IconEmailAttention className={css.modalIcon} />
|
||||
<p className={css.modalTitle}>
|
||||
<FormattedMessage id="ModalMissingInformation.verifyEmailTitle" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="ModalMissingInformation.verifyEmailText" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="ModalMissingInformation.checkInbox" values={{ email }} />
|
||||
</p>
|
||||
{resendErrorMessage}
|
||||
|
||||
<div className={css.bottomWrapper}>
|
||||
<p className={css.helperText}>
|
||||
{sendVerificationEmailInProgress ? (
|
||||
<FormattedMessage id="ModalMissingInformation.sendingEmail" />
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="ModalMissingInformation.resendEmail"
|
||||
values={{ resendEmailLink }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
<p className={css.helperText}>
|
||||
<FormattedMessage id="ModalMissingInformation.fixEmail" values={{ fixEmailLink }} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmailReminder;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
.root {
|
||||
/* Adding empty .root class to enforce className overwrite */
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import React, { Component } from 'react';
|
||||
import { bool, func, string } from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import routeConfiguration from '../../routeConfiguration';
|
||||
import { ensureCurrentUser } from '../../util/data';
|
||||
import { propTypes } from '../../util/types';
|
||||
import { pathByRouteName } from '../../util/routes';
|
||||
import { Modal } from '../../components';
|
||||
|
||||
import EmailReminder from './EmailReminder';
|
||||
import StripeAccountReminder from './StripeAccountReminder';
|
||||
import css from './ModalMissingInformation.css';
|
||||
|
||||
const MISSING_INFORMATION_MODAL_WHITELIST = [
|
||||
'LoginPage',
|
||||
'SignupPage',
|
||||
'ContactDetailsPage',
|
||||
'EmailVerificationPage',
|
||||
'PasswordResetPage',
|
||||
'PayoutPreferencesPage',
|
||||
];
|
||||
|
||||
const EMAIL_VERIFICATION = 'EMAIL_VERIFICATION';
|
||||
const STRIPE_ACCOUNT = 'STRIPE_ACCOUNT';
|
||||
|
||||
class ModalMissingInformation extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showMissingInformationReminder: null,
|
||||
hasSeenMissingInformationReminder: false,
|
||||
};
|
||||
this.handleMissingInformationReminder = this.handleMissingInformationReminder.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentUser, currentUserHasListings, currentUserHasOrders, location } = nextProps;
|
||||
const user = ensureCurrentUser(currentUser);
|
||||
this.handleMissingInformationReminder(
|
||||
user,
|
||||
currentUserHasListings,
|
||||
currentUserHasOrders,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
handleMissingInformationReminder(
|
||||
currentUser,
|
||||
currentUserHasListings,
|
||||
currentUserHasOrders,
|
||||
newLocation
|
||||
) {
|
||||
const routes = routeConfiguration();
|
||||
const whitelistedPaths = MISSING_INFORMATION_MODAL_WHITELIST.map(page =>
|
||||
pathByRouteName(page, routes)
|
||||
);
|
||||
|
||||
// Is the current page whitelisted?
|
||||
const isPageWhitelisted = whitelistedPaths.includes(newLocation.pathname);
|
||||
|
||||
// Track if path changes inside Page level component
|
||||
const pathChanged = newLocation.pathname !== this.props.location.pathname;
|
||||
const notRemindedYet =
|
||||
!this.state.showMissingInformationReminder && !this.state.hasSeenMissingInformationReminder;
|
||||
|
||||
// Is the reminder already shown on current page
|
||||
const showOnPathChange = notRemindedYet || pathChanged;
|
||||
|
||||
if (!isPageWhitelisted && showOnPathChange) {
|
||||
// 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;
|
||||
|
||||
const emailUnverified = !!currentUser.id && !currentUser.attributes.emailVerified;
|
||||
const emailVerificationNeeded = hasListingsOrOrders && emailUnverified;
|
||||
|
||||
const stripeAccountMissing = !!currentUser.id && !currentUser.attributes.stripeConnected;
|
||||
const stripeAccountNeeded = currentUserHasListings && stripeAccountMissing;
|
||||
|
||||
// Show reminder
|
||||
if (emailVerificationNeeded) {
|
||||
this.setState({ showMissingInformationReminder: EMAIL_VERIFICATION });
|
||||
} else if (stripeAccountNeeded) {
|
||||
this.setState({ showMissingInformationReminder: STRIPE_ACCOUNT });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
containerClassName,
|
||||
currentUser,
|
||||
sendVerificationEmailInProgress,
|
||||
sendVerificationEmailError,
|
||||
onManageDisableScrolling,
|
||||
onResendVerificationEmail,
|
||||
} = this.props;
|
||||
|
||||
const user = ensureCurrentUser(currentUser);
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
let content = null;
|
||||
|
||||
const currentUserLoaded = user && user.id;
|
||||
if (currentUserLoaded) {
|
||||
if (this.state.showMissingInformationReminder === EMAIL_VERIFICATION) {
|
||||
content = (
|
||||
<EmailReminder
|
||||
className={classes}
|
||||
user={user}
|
||||
onResendVerificationEmail={onResendVerificationEmail}
|
||||
sendVerificationEmailInProgress={sendVerificationEmailInProgress}
|
||||
sendVerificationEmailError={sendVerificationEmailError}
|
||||
/>
|
||||
);
|
||||
} else if (this.state.showMissingInformationReminder === STRIPE_ACCOUNT) {
|
||||
content = <StripeAccountReminder className={classes} />;
|
||||
}
|
||||
}
|
||||
|
||||
const closeButtonMessage = (
|
||||
<FormattedMessage id="ModalMissingInformation.closeVerifyEmailReminder" />
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
id="MissingInformationReminder"
|
||||
containerClassName={containerClassName}
|
||||
isOpen={!!this.state.showMissingInformationReminder}
|
||||
onClose={() => {
|
||||
this.setState({
|
||||
showMissingInformationReminder: null,
|
||||
hasSeenMissingInformationReminder: true,
|
||||
});
|
||||
}}
|
||||
onManageDisableScrolling={onManageDisableScrolling}
|
||||
closeButtonMessage={closeButtonMessage}
|
||||
>
|
||||
{content}
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ModalMissingInformation.defaultProps = {
|
||||
className: null,
|
||||
rootClassName: null,
|
||||
currentUser: null,
|
||||
};
|
||||
|
||||
ModalMissingInformation.propTypes = {
|
||||
id: string.isRequired,
|
||||
className: string,
|
||||
rootClassName: string,
|
||||
containerClassName: string,
|
||||
|
||||
currentUser: propTypes.currentUser,
|
||||
onManageDisableScrolling: func.isRequired,
|
||||
sendVerificationEmailError: propTypes.error,
|
||||
sendVerificationEmailInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
ModalMissingInformation.displayName = 'ModalMissingInformation';
|
||||
|
||||
export default ModalMissingInformation;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { NamedLink } from '../../components';
|
||||
|
||||
import css from './ModalMissingInformation.css';
|
||||
|
||||
const StripeAccountReminder = props => {
|
||||
const { className } = props;
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<p className={css.modalTitle}>
|
||||
<FormattedMessage id="ModalMissingInformation.missingStripeAccountTitle" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="ModalMissingInformation.missingStripeAccountText" />
|
||||
</p>
|
||||
<div className={css.bottomWrapper}>
|
||||
<NamedLink className={css.reminderModalLinkButton} name="PayoutPreferencesPage">
|
||||
<FormattedMessage id="ModalMissingInformation.gotoPaymentSettings" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StripeAccountReminder;
|
||||
|
|
@ -6,18 +6,15 @@ import pickBy from 'lodash/pickBy';
|
|||
import classNames from 'classnames';
|
||||
import config from '../../config';
|
||||
import routeConfiguration from '../../routeConfiguration';
|
||||
import { ensureCurrentUser } from '../../util/data';
|
||||
import { withViewport } from '../../util/contextHelpers';
|
||||
import { parse, stringify } from '../../util/urlHelpers';
|
||||
import { createResourceLocatorString, pathByRouteName } from '../../util/routes';
|
||||
import { propTypes } from '../../util/types';
|
||||
import { isTooManyEmailVerificationRequestsError } from '../../util/errors';
|
||||
import {
|
||||
Button,
|
||||
IconEmailAttention,
|
||||
InlineTextButton,
|
||||
Logo,
|
||||
Modal,
|
||||
ModalMissingInformation,
|
||||
NamedLink,
|
||||
TopbarDesktop,
|
||||
TopbarMobileMenu,
|
||||
|
|
@ -29,14 +26,6 @@ import SearchIcon from './SearchIcon';
|
|||
import css from './Topbar.css';
|
||||
|
||||
const MAX_MOBILE_SCREEN_WIDTH = 768;
|
||||
const MISSING_INFORMATION_MODAL_WHITELIST = [
|
||||
'LoginPage',
|
||||
'SignupPage',
|
||||
'ContactDetailsPage',
|
||||
'EmailVerificationPage',
|
||||
'PasswordResetPage',
|
||||
'PayoutPreferencesPage',
|
||||
];
|
||||
|
||||
const redirectToURLWithModalState = (props, modalStateParam) => {
|
||||
const { history, location } = props;
|
||||
|
|
@ -78,81 +67,9 @@ GenericError.propTypes = {
|
|||
show: bool.isRequired,
|
||||
};
|
||||
|
||||
const ReminderModalContent = props => {
|
||||
const {
|
||||
currentUser,
|
||||
email,
|
||||
resendErrorMessage,
|
||||
sendVerificationEmailInProgress,
|
||||
resendEmailLink,
|
||||
fixEmailLink,
|
||||
} = props;
|
||||
const emailVerificationMissingContent = (
|
||||
<div>
|
||||
<IconEmailAttention className={css.modalIcon} />
|
||||
<p className={css.modalTitle}>
|
||||
<FormattedMessage id="Topbar.verifyEmailTitle" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="Topbar.verifyEmailText" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="Topbar.checkInbox" values={{ email }} />
|
||||
</p>
|
||||
{resendErrorMessage}
|
||||
|
||||
<div className={css.bottomWrapper}>
|
||||
<p className={css.helperText}>
|
||||
{sendVerificationEmailInProgress ? (
|
||||
<FormattedMessage id="Topbar.sendingEmail" />
|
||||
) : (
|
||||
<FormattedMessage id="Topbar.resendEmail" values={{ resendEmailLink }} />
|
||||
)}
|
||||
</p>
|
||||
<p className={css.helperText}>
|
||||
<FormattedMessage id="Topbar.fixEmail" values={{ fixEmailLink }} />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const stripeAccountMissingContent = (
|
||||
<div>
|
||||
<p className={css.modalTitle}>
|
||||
<FormattedMessage id="Topbar.missingStripeAccountTitle" />
|
||||
</p>
|
||||
<p className={css.modalMessage}>
|
||||
<FormattedMessage id="Topbar.missingStripeAccountText" />
|
||||
</p>
|
||||
<div className={css.bottomWrapper}>
|
||||
<NamedLink className={css.reminderModalLinkButton} name="PayoutPreferencesPage">
|
||||
<FormattedMessage id="Topbar.gotoPaymentSettings" />
|
||||
</NamedLink>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const currentUserLoaded = currentUser && currentUser.id;
|
||||
let content = null;
|
||||
|
||||
if (currentUserLoaded && !currentUser.attributes.emailVerified) {
|
||||
content = emailVerificationMissingContent;
|
||||
} else if (currentUserLoaded && !currentUser.attributes.stripeConnected) {
|
||||
content = stripeAccountMissingContent;
|
||||
}
|
||||
|
||||
return content;
|
||||
};
|
||||
|
||||
class TopbarComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
showMissingInformationReminder: false,
|
||||
hasSeenMissingInformationReminder: false,
|
||||
};
|
||||
|
||||
this.onHistoryChanged = this.handleMissingInformationReminder.bind(this);
|
||||
this.handleMobileMenuOpen = this.handleMobileMenuOpen.bind(this);
|
||||
this.handleMobileMenuClose = this.handleMobileMenuClose.bind(this);
|
||||
this.handleMobileSearchOpen = this.handleMobileSearchOpen.bind(this);
|
||||
|
|
@ -161,52 +78,6 @@ class TopbarComponent extends Component {
|
|||
this.handleLogout = this.handleLogout.bind(this);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
const { currentUser, currentUserHasListings, currentUserHasOrders, location } = nextProps;
|
||||
const user = ensureCurrentUser(currentUser);
|
||||
this.handleMissingInformationReminder(
|
||||
user,
|
||||
currentUserHasListings,
|
||||
currentUserHasOrders,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
handleMissingInformationReminder(
|
||||
currentUser,
|
||||
currentUserHasListings,
|
||||
currentUserHasOrders,
|
||||
newLocation
|
||||
) {
|
||||
// Track if path changes inside Page level component
|
||||
const pathChanged = newLocation.pathname !== this.props.location.pathname;
|
||||
const emailUnverified = !!currentUser.id && !currentUser.attributes.emailVerified;
|
||||
const stripeAccountMissing = !!currentUser.id && !currentUser.attributes.stripeConnected;
|
||||
const infoMissing = emailUnverified || (currentUserHasListings && stripeAccountMissing);
|
||||
const notRemindedYet =
|
||||
!this.state.showMissingInformationReminder && !this.state.hasSeenMissingInformationReminder;
|
||||
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;
|
||||
|
||||
const routes = routeConfiguration();
|
||||
const whitelistedPaths = MISSING_INFORMATION_MODAL_WHITELIST.map(page =>
|
||||
pathByRouteName(page, routes)
|
||||
);
|
||||
const isNotWhitelisted = !whitelistedPaths.includes(newLocation.pathname);
|
||||
|
||||
const showReminder = infoMissing && isNotWhitelisted && hasListingsOrOrders && showOnPathChange;
|
||||
|
||||
// Show reminder
|
||||
if (showReminder) {
|
||||
this.setState({ showMissingInformationReminder: true });
|
||||
}
|
||||
}
|
||||
|
||||
handleMobileMenuOpen() {
|
||||
redirectToURLWithModalState(this.props, 'mobilemenu');
|
||||
}
|
||||
|
|
@ -267,6 +138,7 @@ class TopbarComponent extends Component {
|
|||
authInProgress,
|
||||
currentUser,
|
||||
currentUserHasListings,
|
||||
currentUserHasOrders,
|
||||
currentPage,
|
||||
notificationCount,
|
||||
viewport,
|
||||
|
|
@ -312,32 +184,6 @@ class TopbarComponent extends Component {
|
|||
: null,
|
||||
};
|
||||
|
||||
const user = ensureCurrentUser(currentUser);
|
||||
const email = user.id ? <span className={css.email}>{user.attributes.email}</span> : '';
|
||||
|
||||
const resendEmailLink = (
|
||||
<InlineTextButton className={css.helperLink} onClick={onResendVerificationEmail}>
|
||||
<FormattedMessage id="Topbar.resendEmailLinkText" />
|
||||
</InlineTextButton>
|
||||
);
|
||||
const fixEmailLink = (
|
||||
<NamedLink className={css.helperLink} name="ContactDetailsPage">
|
||||
<FormattedMessage id="Topbar.fixEmailLinkText" />
|
||||
</NamedLink>
|
||||
);
|
||||
|
||||
const resendErrorTranslationId = isTooManyEmailVerificationRequestsError(
|
||||
sendVerificationEmailError
|
||||
)
|
||||
? 'Topbar.resendFailedTooManyRequests'
|
||||
: 'Topbar.resendFailed';
|
||||
const resendErrorMessage = sendVerificationEmailError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id={resendErrorTranslationId} />
|
||||
</p>
|
||||
) : null;
|
||||
const closeButtonMessage = <FormattedMessage id="Topbar.closeVerifyEmailReminder" />;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
|
|
@ -407,29 +253,19 @@ class TopbarComponent extends Component {
|
|||
</p>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
<ModalMissingInformation
|
||||
id="MissingInformationReminder"
|
||||
containerClassName={css.missingInformationModal}
|
||||
isOpen={this.state.showMissingInformationReminder}
|
||||
onClose={() => {
|
||||
this.setState({
|
||||
showMissingInformationReminder: false,
|
||||
hasSeenMissingInformationReminder: true,
|
||||
});
|
||||
}}
|
||||
currentUser={currentUser}
|
||||
currentUserHasListings={currentUserHasListings}
|
||||
currentUserHasOrders={currentUserHasOrders}
|
||||
location={location}
|
||||
onManageDisableScrolling={onManageDisableScrolling}
|
||||
closeButtonMessage={closeButtonMessage}
|
||||
>
|
||||
<ReminderModalContent
|
||||
currentUser={currentUser}
|
||||
email={email}
|
||||
resendErrorMessage={resendErrorMessage}
|
||||
sendVerificationEmailInProgress={sendVerificationEmailInProgress}
|
||||
resendEmailLink={resendEmailLink}
|
||||
fixEmailLink={fixEmailLink}
|
||||
/>
|
||||
</Modal>
|
||||
onResendVerificationEmail={onResendVerificationEmail}
|
||||
sendVerificationEmailInProgress={sendVerificationEmailInProgress}
|
||||
sendVerificationEmailError={sendVerificationEmailError}
|
||||
/>
|
||||
|
||||
<GenericError show={showGenericError} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ export { default as MenuItem } from './MenuItem/MenuItem';
|
|||
export { default as MenuLabel } from './MenuLabel/MenuLabel';
|
||||
export { default as Modal } from './Modal/Modal';
|
||||
export { default as ModalInMobile } from './ModalInMobile/ModalInMobile';
|
||||
export {
|
||||
default as ModalMissingInformation,
|
||||
} from './ModalMissingInformation/ModalMissingInformation';
|
||||
export { default as NamedLink } from './NamedLink/NamedLink';
|
||||
export { default as NamedRedirect } from './NamedRedirect/NamedRedirect';
|
||||
export { default as NotificationBadge } from './NotificationBadge/NotificationBadge';
|
||||
|
|
|
|||
|
|
@ -333,6 +333,20 @@
|
|||
"MapPriceMarker.unsupportedPrice": "({currency})",
|
||||
"Modal.close": "CLOSE",
|
||||
"Modal.closeModal": "Close modal",
|
||||
"ModalMissingInformation.checkInbox": "Please check your inbox and verify your email address {email}",
|
||||
"ModalMissingInformation.closeVerifyEmailReminder": "Later",
|
||||
"ModalMissingInformation.fixEmail": "Whoops, typo in your email? {fixEmailLink}",
|
||||
"ModalMissingInformation.fixEmailLinkText": "Fix it.",
|
||||
"ModalMissingInformation.gotoPaymentSettings": "Add payment details",
|
||||
"ModalMissingInformation.missingStripeAccountText": "You have listings but your payment details are missing. Your listings cannot be booked until the details are saved.",
|
||||
"ModalMissingInformation.missingStripeAccountTitle": "Payment details missing",
|
||||
"ModalMissingInformation.resendEmail": "Didn't get the email? {resendEmailLink}",
|
||||
"ModalMissingInformation.resendEmailLinkText": "Resend it.",
|
||||
"ModalMissingInformation.resendFailed": "Resending verification email failed. Please try again.",
|
||||
"ModalMissingInformation.resendFailedTooManyRequests": "Resending verification email failed. You already have too many verification emails sent.",
|
||||
"ModalMissingInformation.sendingEmail": "Sending verification email…",
|
||||
"ModalMissingInformation.verifyEmailText": "We are currently unable to send you email notifications if other Saunatime users contact you because you haven't verified your email address.",
|
||||
"ModalMissingInformation.verifyEmailTitle": "Please verify your email address",
|
||||
"NotFoundPage.description": "We can't find the page or sauna you're looking for. Make sure you've typed in the URL correctly or try searching Saunatime.",
|
||||
"NotFoundPage.heading": "Sorry, we couldn't find that page.",
|
||||
"NotFoundPage.title": "Page not found",
|
||||
|
|
@ -636,25 +650,11 @@
|
|||
"TermsOfServicePage.privacyTabTitle": "Privacy Policy",
|
||||
"TermsOfServicePage.schemaTitle": "Terms of Service | {siteTitle}",
|
||||
"TermsOfServicePage.tosTabTitle": "Terms of Service",
|
||||
"Topbar.checkInbox": "Please check your inbox and verify your email address {email}",
|
||||
"Topbar.closeVerifyEmailReminder": "Later",
|
||||
"Topbar.fixEmail": "Whoops, typo in your email? {fixEmailLink}",
|
||||
"Topbar.fixEmailLinkText": "Fix it.",
|
||||
"Topbar.genericError": "Oh no, something went wrong. Please check your network connection and try again.",
|
||||
"Topbar.gotoPaymentSettings": "Add payment details",
|
||||
"Topbar.logoIcon": "Go to homepage",
|
||||
"Topbar.menuIcon": "Open menu",
|
||||
"Topbar.missingStripeAccountText": "You have listings but your payment details are missing. Your listings cannot be booked until the details are saved.",
|
||||
"Topbar.missingStripeAccountTitle": "Payment details missing",
|
||||
"Topbar.mobileSearchHelp": "Tip: You can also search saunas by zip code, for example \"00500\" or city district – \"Sörnäinen\".",
|
||||
"Topbar.resendEmail": "Didn't get the email? {resendEmailLink}",
|
||||
"Topbar.resendEmailLinkText": "Resend it.",
|
||||
"Topbar.resendFailed": "Resending verification email failed. Please try again.",
|
||||
"Topbar.resendFailedTooManyRequests": "Resending verification email failed. You already have too many verification emails sent.",
|
||||
"Topbar.searchIcon": "Open search",
|
||||
"Topbar.sendingEmail": "Sending verification email…",
|
||||
"Topbar.verifyEmailText": "We are currently unable to send you email notifications if other Saunatime users contact you because you haven't verified your email address.",
|
||||
"Topbar.verifyEmailTitle": "Please verify your email address",
|
||||
"TopbarDesktop.accountSettingsLink": "Account settings",
|
||||
"TopbarDesktop.createListing": "+ Add your sauna",
|
||||
"TopbarDesktop.inbox": "Inbox",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue