mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 03:43:28 +10:00
Merge pull request #665 from sharetribe/policypanel
EditListingPolicyPanel aka Sauna rules
This commit is contained in:
commit
5bd7ae1249
13 changed files with 401 additions and 53 deletions
|
|
@ -0,0 +1,22 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 11px 24px 0 24px;
|
||||
}
|
||||
|
||||
.form {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 19px;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin-bottom: 44px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { ensureListing } from '../../util/data';
|
||||
import { createSlug } from '../../util/urlHelpers';
|
||||
import { NamedLink } from '../../components';
|
||||
import { EditListingPoliciesForm } from '../../containers';
|
||||
|
||||
import css from './EditListingPoliciesPanel.css';
|
||||
|
||||
const EditListingPoliciesPanel = props => {
|
||||
const {
|
||||
className,
|
||||
rootClassName,
|
||||
listing,
|
||||
onSubmit,
|
||||
onChange,
|
||||
submitButtonText,
|
||||
panelUpdated,
|
||||
updateInProgress,
|
||||
errors,
|
||||
} = props;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const currentListing = ensureListing(listing);
|
||||
const { title, publicData } = currentListing.attributes;
|
||||
const listingTitle = title || '';
|
||||
const listingLink = currentListing.id ? (
|
||||
<NamedLink name="ListingPage" params={{ id: currentListing.id.uuid, slug: createSlug(title) }}>
|
||||
{listingTitle}
|
||||
</NamedLink>
|
||||
) : (
|
||||
''
|
||||
);
|
||||
|
||||
const panelTitle = currentListing.id ? (
|
||||
<FormattedMessage id="EditListingPoliciesPanel.title" values={{ listingTitle: listingLink }} />
|
||||
) : (
|
||||
<FormattedMessage id="EditListingPoliciesPanel.createListingTitle" />
|
||||
);
|
||||
|
||||
const saunaRules = publicData && publicData.saunaRules ? publicData.saunaRules : '';
|
||||
const initialSearchFormValues = { saunaRules };
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<h1 className={css.title}>{panelTitle}</h1>
|
||||
<EditListingPoliciesForm
|
||||
className={css.form}
|
||||
initialValues={initialSearchFormValues}
|
||||
onSubmit={onSubmit}
|
||||
onChange={onChange}
|
||||
saveActionMsg={submitButtonText}
|
||||
updated={panelUpdated}
|
||||
updateError={errors.updateListingError}
|
||||
updateInProgress={updateInProgress}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const { func, object, string, bool } = PropTypes;
|
||||
|
||||
EditListingPoliciesPanel.defaultProps = {
|
||||
className: null,
|
||||
rootClassName: null,
|
||||
listing: null,
|
||||
};
|
||||
|
||||
EditListingPoliciesPanel.propTypes = {
|
||||
className: string,
|
||||
rootClassName: string,
|
||||
|
||||
// We cannot use propTypes.listing since the listing might be a draft.
|
||||
listing: object,
|
||||
|
||||
onSubmit: func.isRequired,
|
||||
onChange: func.isRequired,
|
||||
submitButtonText: string.isRequired,
|
||||
panelUpdated: bool.isRequired,
|
||||
updateInProgress: bool.isRequired,
|
||||
errors: object.isRequired,
|
||||
};
|
||||
|
||||
export default EditListingPoliciesPanel;
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
.tab {
|
||||
margin-left: 16px;
|
||||
white-space: nowrap;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
EditListingDescriptionPanel,
|
||||
EditListingLocationPanel,
|
||||
EditListingPhotosPanel,
|
||||
EditListingPoliciesPanel,
|
||||
EditListingPricingPanel,
|
||||
NamedRedirect,
|
||||
Tabs,
|
||||
|
|
@ -20,10 +21,11 @@ import {
|
|||
import css from './EditListingWizard.css';
|
||||
|
||||
const DESCRIPTION = 'description';
|
||||
const POLICY = 'policy';
|
||||
const LOCATION = 'location';
|
||||
const PRICING = 'pricing';
|
||||
const PHOTOS = 'photos';
|
||||
const STEPS = [DESCRIPTION, LOCATION, PRICING, PHOTOS];
|
||||
const STEPS = [DESCRIPTION, POLICY, LOCATION, PRICING, PHOTOS];
|
||||
|
||||
// Tabs are horizontal in small screens
|
||||
const MAX_HORIZONTAL_NAV_SCREEN_WIDTH = 1023;
|
||||
|
|
@ -32,6 +34,8 @@ const submitText = (intl, isNew, step) => {
|
|||
let key = null;
|
||||
if (step === DESCRIPTION) {
|
||||
key = isNew ? 'EditListingWizard.saveNewDescription' : 'EditListingWizard.saveEditDescription';
|
||||
} else if (step === POLICY) {
|
||||
key = isNew ? 'EditListingWizard.saveNewPolicies' : 'EditListingWizard.saveEditPolicies';
|
||||
} else if (step === LOCATION) {
|
||||
key = isNew ? 'EditListingWizard.saveNewLocation' : 'EditListingWizard.saveEditLocation';
|
||||
} else if (step === PRICING) {
|
||||
|
|
@ -42,6 +46,22 @@ const submitText = (intl, isNew, step) => {
|
|||
return intl.formatMessage({ id: key });
|
||||
};
|
||||
|
||||
const tabLabel = (intl, step) => {
|
||||
let key = null;
|
||||
if (step === DESCRIPTION) {
|
||||
key = 'EditListingWizard.tabLabelDescription';
|
||||
} else if (step === POLICY) {
|
||||
key = 'EditListingWizard.tabLabelPolicy';
|
||||
} else if (step === LOCATION) {
|
||||
key = 'EditListingWizard.tabLabelLocation';
|
||||
} else if (step === PRICING) {
|
||||
key = 'EditListingWizard.tabLabelPricing';
|
||||
} else if (step === PHOTOS) {
|
||||
key = 'EditListingWizard.tabLabelPhotos';
|
||||
}
|
||||
return intl.formatMessage({ id: key });
|
||||
};
|
||||
|
||||
/**
|
||||
* Check which wizard steps are active and which are not yet available. Step is active is previous
|
||||
* step is completed.
|
||||
|
|
@ -53,6 +73,7 @@ const submitText = (intl, isNew, step) => {
|
|||
const stepsActive = listing => {
|
||||
const { description, geolocation, price, title, publicData } = listing.attributes;
|
||||
const descriptionStep = !!(title && description);
|
||||
const policyStep = !!(publicData && typeof publicData.saunaRules !== 'undefined');
|
||||
const locationStep = !!(
|
||||
geolocation &&
|
||||
publicData &&
|
||||
|
|
@ -65,7 +86,8 @@ const stepsActive = listing => {
|
|||
|
||||
return {
|
||||
[DESCRIPTION]: true,
|
||||
[LOCATION]: descriptionStep,
|
||||
[POLICY]: descriptionStep,
|
||||
[LOCATION]: policyStep,
|
||||
[PRICING]: locationStep,
|
||||
[PHOTOS]: pricingStep,
|
||||
};
|
||||
|
|
@ -160,21 +182,27 @@ class EditListingWizard extends Component {
|
|||
this.hasScrolledToTab = true;
|
||||
}
|
||||
|
||||
const panelProps = tab => {
|
||||
return {
|
||||
className: css.panel,
|
||||
disabled: !stepsStatus[tab],
|
||||
errors,
|
||||
listing,
|
||||
onChange,
|
||||
panelUpdated: updatedTab === tab,
|
||||
selected: selectedTab === tab,
|
||||
submitButtonText: submitText(intl, isNew, tab),
|
||||
tabId: `${id}_${tab}`,
|
||||
tabLabel: tabLabel(intl, tab),
|
||||
tabLinkProps: tabLink(tab),
|
||||
updateInProgress,
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs rootClassName={classes} navRootClassName={css.nav} tabRootClassName={css.tab}>
|
||||
<EditListingDescriptionPanel
|
||||
className={css.panel}
|
||||
tabId={`${id}_a${DESCRIPTION}`}
|
||||
tabLabel={intl.formatMessage({ id: 'EditListingWizard.tabLabelDescription' })}
|
||||
tabLinkProps={tabLink(DESCRIPTION)}
|
||||
selected={selectedTab === DESCRIPTION}
|
||||
panelUpdated={updatedTab === DESCRIPTION}
|
||||
updateInProgress={updateInProgress}
|
||||
disabled={!stepsStatus[DESCRIPTION]}
|
||||
errors={errors}
|
||||
listing={listing}
|
||||
submitButtonText={submitText(intl, isNew, DESCRIPTION)}
|
||||
onChange={onChange}
|
||||
{...panelProps(DESCRIPTION)}
|
||||
onSubmit={values => {
|
||||
const { title, description, category } = values;
|
||||
const updateValues = {
|
||||
|
|
@ -186,7 +214,7 @@ class EditListingWizard extends Component {
|
|||
|
||||
if (isNew) {
|
||||
onUpsertListingDraft(updateValues);
|
||||
const pathParams = tabParams(LOCATION);
|
||||
const pathParams = tabParams(POLICY);
|
||||
// Redirect to location tab
|
||||
history.push(
|
||||
createResourceLocatorString('EditListingPage', routeConfiguration(), pathParams, {})
|
||||
|
|
@ -196,19 +224,30 @@ class EditListingWizard extends Component {
|
|||
}
|
||||
}}
|
||||
/>
|
||||
<EditListingPoliciesPanel
|
||||
{...panelProps(POLICY)}
|
||||
onSubmit={values => {
|
||||
const { saunaRules = '' } = values;
|
||||
const updateValues = {
|
||||
publicData: {
|
||||
saunaRules,
|
||||
},
|
||||
};
|
||||
|
||||
if (isNew) {
|
||||
onUpdateListingDraft(updateValues);
|
||||
const pathParams = tabParams(LOCATION);
|
||||
// Redirect to pricing tab
|
||||
history.push(
|
||||
createResourceLocatorString('EditListingPage', routeConfiguration(), pathParams, {})
|
||||
);
|
||||
} else {
|
||||
update(POLICY, updateValues);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<EditListingLocationPanel
|
||||
className={css.panel}
|
||||
tabId={`${id}_${LOCATION}`}
|
||||
tabLabel={intl.formatMessage({ id: 'EditListingWizard.tabLabelLocation' })}
|
||||
tabLinkProps={tabLink(LOCATION)}
|
||||
selected={selectedTab === LOCATION}
|
||||
panelUpdated={updatedTab === LOCATION}
|
||||
updateInProgress={updateInProgress}
|
||||
disabled={!stepsStatus[LOCATION]}
|
||||
errors={errors}
|
||||
listing={listing}
|
||||
submitButtonText={submitText(intl, isNew, LOCATION)}
|
||||
onChange={onChange}
|
||||
{...panelProps(LOCATION)}
|
||||
onSubmit={values => {
|
||||
const { building = '', location } = values;
|
||||
const { selectedPlace: { address, origin } } = location;
|
||||
|
|
@ -220,7 +259,6 @@ class EditListingWizard extends Component {
|
|||
};
|
||||
|
||||
if (isNew) {
|
||||
// TODO When API supports building number, etc. change this to use those fields instead.
|
||||
onUpdateListingDraft(updateValues);
|
||||
const pathParams = tabParams(PRICING);
|
||||
// Redirect to pricing tab
|
||||
|
|
@ -233,18 +271,7 @@ class EditListingWizard extends Component {
|
|||
}}
|
||||
/>
|
||||
<EditListingPricingPanel
|
||||
className={css.panel}
|
||||
tabId={`${id}_${PRICING}`}
|
||||
tabLabel={intl.formatMessage({ id: 'EditListingWizard.tabLabelPricing' })}
|
||||
tabLinkProps={tabLink(PRICING)}
|
||||
selected={selectedTab === PRICING}
|
||||
panelUpdated={updatedTab === PRICING}
|
||||
updateInProgress={updateInProgress}
|
||||
disabled={!stepsStatus[PRICING]}
|
||||
errors={errors}
|
||||
listing={listing}
|
||||
submitButtonText={submitText(intl, isNew, PRICING)}
|
||||
onChange={onChange}
|
||||
{...panelProps(PRICING)}
|
||||
onSubmit={values => {
|
||||
if (isNew) {
|
||||
onUpdateListingDraft(values);
|
||||
|
|
@ -259,25 +286,14 @@ class EditListingWizard extends Component {
|
|||
}}
|
||||
/>
|
||||
<EditListingPhotosPanel
|
||||
className={css.panel}
|
||||
tabId={`${id}_${PHOTOS}`}
|
||||
tabLabel={intl.formatMessage({ id: 'EditListingWizard.tabLabelPhotos' })}
|
||||
tabLinkProps={tabLink(PHOTOS)}
|
||||
selected={selectedTab === PHOTOS}
|
||||
disabled={!stepsStatus[PHOTOS]}
|
||||
panelUpdated={updatedTab === PHOTOS}
|
||||
{...panelProps(PHOTOS)}
|
||||
newListingCreated={newListingCreated}
|
||||
updateInProgress={updateInProgress}
|
||||
errors={errors}
|
||||
fetchInProgress={fetchInProgress}
|
||||
listing={listing}
|
||||
images={images}
|
||||
onImageUpload={onImageUpload}
|
||||
onRemoveImage={onRemoveImage}
|
||||
onPayoutDetailsFormChange={onPayoutDetailsFormChange}
|
||||
onPayoutDetailsSubmit={onPayoutDetailsSubmit}
|
||||
submitButtonText={submitText(intl, isNew, PHOTOS)}
|
||||
onChange={onChange}
|
||||
onSubmit={values => {
|
||||
const { country, images: updatedImages } = values;
|
||||
const updateValues = { ...listing.attributes, country, images: updatedImages };
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ export {
|
|||
default as EditListingLocationPanel,
|
||||
} from './EditListingLocationPanel/EditListingLocationPanel';
|
||||
export { default as EditListingPhotosPanel } from './EditListingPhotosPanel/EditListingPhotosPanel';
|
||||
export {
|
||||
default as EditListingPoliciesPanel,
|
||||
} from './EditListingPoliciesPanel/EditListingPoliciesPanel';
|
||||
export {
|
||||
default as EditListingPricingPanel,
|
||||
} from './EditListingPricingPanel/EditListingPricingPanel';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
:root {
|
||||
--formMargins: {
|
||||
margin-bottom: 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.root {
|
||||
/* Dimensions */
|
||||
width: 100%;
|
||||
height: auto;
|
||||
|
||||
/* Layout */
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
padding-top: 1px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
@apply --formMargins;
|
||||
}
|
||||
|
||||
.policy {
|
||||
@apply --formMargins;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--failColor);
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
margin-top: auto;
|
||||
margin-bottom: 24px;
|
||||
flex-shrink: 0;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
display: inline-block;
|
||||
width: 241px;
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/* eslint-disable no-console */
|
||||
import EditListingPoliciesForm from './EditListingPoliciesForm';
|
||||
|
||||
export const Empty = {
|
||||
component: EditListingPoliciesForm,
|
||||
props: {
|
||||
onSubmit: values => {
|
||||
console.log('Submit EditListingPoliciesForm with (unformatted) values:', values);
|
||||
},
|
||||
saveActionMsg: 'Save rules',
|
||||
updated: false,
|
||||
updateInProgress: false,
|
||||
},
|
||||
group: 'forms',
|
||||
};
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { reduxForm, propTypes as formPropTypes } from 'redux-form';
|
||||
import { intlShape, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { propTypes } from '../../util/types';
|
||||
import { Form, Button, TextInputField } from '../../components';
|
||||
|
||||
import css from './EditListingPoliciesForm.css';
|
||||
|
||||
export const EditListingPoliciesFormComponent = props => {
|
||||
const {
|
||||
className,
|
||||
disabled,
|
||||
handleSubmit,
|
||||
intl,
|
||||
form,
|
||||
invalid,
|
||||
saveActionMsg,
|
||||
submitting,
|
||||
updated,
|
||||
updateError,
|
||||
updateInProgress,
|
||||
} = props;
|
||||
|
||||
const rulesLabelMessage = intl.formatMessage({ id: 'EditListingPoliciesForm.rulesLabel' });
|
||||
const saunaRulesPlaceholderMessage = intl.formatMessage({
|
||||
id: 'EditListingPoliciesForm.rulesPlaceholder',
|
||||
});
|
||||
|
||||
const errorMessage = updateError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="EditListingPoliciesForm.updateFailed" />
|
||||
</p>
|
||||
) : null;
|
||||
|
||||
const classes = classNames(css.root, className);
|
||||
const submitReady = updated;
|
||||
const submitInProgress = submitting || updateInProgress;
|
||||
const submitDisabled = invalid || disabled || submitInProgress;
|
||||
|
||||
return (
|
||||
<Form className={classes} onSubmit={handleSubmit}>
|
||||
{errorMessage}
|
||||
|
||||
<TextInputField
|
||||
className={css.policy}
|
||||
type="textarea"
|
||||
name="saunaRules"
|
||||
id={`${form}.saunaRules`}
|
||||
label={rulesLabelMessage}
|
||||
placeholder={saunaRulesPlaceholderMessage}
|
||||
/>
|
||||
|
||||
<Button
|
||||
className={css.submitButton}
|
||||
type="submit"
|
||||
inProgress={submitInProgress}
|
||||
disabled={submitDisabled}
|
||||
ready={submitReady}
|
||||
>
|
||||
{saveActionMsg}
|
||||
</Button>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
EditListingPoliciesFormComponent.defaultProps = {
|
||||
selectedPlace: null,
|
||||
updateError: null,
|
||||
};
|
||||
|
||||
const { func, string, bool } = PropTypes;
|
||||
|
||||
EditListingPoliciesFormComponent.propTypes = {
|
||||
...formPropTypes,
|
||||
intl: intlShape.isRequired,
|
||||
onSubmit: func.isRequired,
|
||||
saveActionMsg: string.isRequired,
|
||||
selectedPlace: propTypes.place,
|
||||
updated: bool.isRequired,
|
||||
updateError: propTypes.error,
|
||||
updateInProgress: bool.isRequired,
|
||||
};
|
||||
|
||||
const formName = 'EditListingPoliciesForm';
|
||||
|
||||
export default compose(reduxForm({ form: formName }), injectIntl)(EditListingPoliciesFormComponent);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// NOTE: renderdeep doesn't work due to Google Maps API integration
|
||||
import React from 'react';
|
||||
import { renderShallow } from '../../util/test-helpers';
|
||||
import { fakeIntl, fakeFormProps } from '../../util/test-data';
|
||||
import { EditListingPoliciesFormComponent } from './EditListingPoliciesForm';
|
||||
|
||||
const noop = () => null;
|
||||
|
||||
describe('EditListingPoliciesForm', () => {
|
||||
it('matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<EditListingPoliciesFormComponent
|
||||
{...fakeFormProps}
|
||||
intl={fakeIntl}
|
||||
dispatch={noop}
|
||||
onSubmit={v => v}
|
||||
saveActionMsg="Save rules"
|
||||
updated={false}
|
||||
updateInProgress={false}
|
||||
/>
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`EditListingPoliciesForm matches snapshot 1`] = `
|
||||
<Form
|
||||
className=""
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<TextInputField
|
||||
id="fakeTestForm.saunaRules"
|
||||
label="EditListingPoliciesForm.rulesLabel"
|
||||
name="saunaRules"
|
||||
placeholder="EditListingPoliciesForm.rulesPlaceholder"
|
||||
type="textarea"
|
||||
/>
|
||||
<Button
|
||||
className={null}
|
||||
disabled={false}
|
||||
inProgress={false}
|
||||
ready={false}
|
||||
rootClassName={null}
|
||||
type="submit"
|
||||
>
|
||||
Save rules
|
||||
</Button>
|
||||
</Form>
|
||||
`;
|
||||
|
|
@ -12,6 +12,9 @@ export {
|
|||
} from './EditListingLocationForm/EditListingLocationForm';
|
||||
export { default as EditListingPage } from './EditListingPage/EditListingPage';
|
||||
export { default as EditListingPhotosForm } from './EditListingPhotosForm/EditListingPhotosForm';
|
||||
export {
|
||||
default as EditListingPoliciesForm,
|
||||
} from './EditListingPoliciesForm/EditListingPoliciesForm';
|
||||
export { default as EditListingPricingForm } from './EditListingPricingForm/EditListingPricingForm';
|
||||
export { default as EmailVerificationForm } from './EmailVerificationForm/EmailVerificationForm';
|
||||
export { default as EmailVerificationPage } from './EmailVerificationPage/EmailVerificationPage';
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ import * as Colors from './containers/StyleguidePage/Colors.example';
|
|||
import * as EditListingDescriptionForm from './containers/EditListingDescriptionForm/EditListingDescriptionForm.example';
|
||||
import * as EditListingLocationForm from './containers/EditListingLocationForm/EditListingLocationForm.example';
|
||||
import * as EditListingPhotosForm from './containers/EditListingPhotosForm/EditListingPhotosForm.example';
|
||||
import * as EditListingPoliciesForm from './containers/EditListingPoliciesForm/EditListingPoliciesForm.example';
|
||||
import * as EditListingPricingForm from './containers/EditListingPricingForm/EditListingPricingForm.example';
|
||||
import * as EmailVerificationForm from './containers/EmailVerificationForm/EmailVerificationForm.example';
|
||||
import * as EnquiryForm from './containers/EnquiryForm/EnquiryForm.example';
|
||||
|
|
@ -85,6 +86,7 @@ export {
|
|||
EditListingDescriptionForm,
|
||||
EditListingLocationForm,
|
||||
EditListingPhotosForm,
|
||||
EditListingPoliciesForm,
|
||||
EditListingPricingForm,
|
||||
EmailVerificationForm,
|
||||
EnquiryForm,
|
||||
|
|
|
|||
|
|
@ -147,6 +147,11 @@
|
|||
"EditListingPhotosPanel.payoutModalTitleOneMoreThing": "One more thing:",
|
||||
"EditListingPhotosPanel.payoutModalTitlePayoutPreferences": "Payout preferences",
|
||||
"EditListingPhotosPanel.title": "Edit the photos of {listingTitle}",
|
||||
"EditListingPoliciesForm.rulesLabel": "Sauna rules",
|
||||
"EditListingPoliciesForm.rulesPlaceholder": "Describe the no-nos",
|
||||
"EditListingPoliciesForm.updateFailed": "Failed to update listing. Please try again.",
|
||||
"EditListingPoliciesPanel.createListingTitle": "Time to set some ground rules for the bathers.",
|
||||
"EditListingPoliciesPanel.title": "Edit the rules of {listingTitle}",
|
||||
"EditListingPricingForm.priceInputPlaceholder": "Choose your price…",
|
||||
"EditListingPricingForm.pricePerUnit": "Price per night in euros",
|
||||
"EditListingPricingForm.priceRequired": "You need to add a valid price.",
|
||||
|
|
@ -157,14 +162,17 @@
|
|||
"EditListingWizard.saveEditDescription": "Save description",
|
||||
"EditListingWizard.saveEditLocation": "Save location",
|
||||
"EditListingWizard.saveEditPhotos": "Save photos",
|
||||
"EditListingWizard.saveEditPolicies": "Save rules",
|
||||
"EditListingWizard.saveEditPricing": "Save pricing",
|
||||
"EditListingWizard.saveNewDescription": "Next: Location",
|
||||
"EditListingWizard.saveNewDescription": "Next: Policies",
|
||||
"EditListingWizard.saveNewLocation": "Next: Pricing",
|
||||
"EditListingWizard.saveNewPhotos": "Publish listing",
|
||||
"EditListingWizard.saveNewPolicies": "Next: location",
|
||||
"EditListingWizard.saveNewPricing": "Next: Photos",
|
||||
"EditListingWizard.tabLabelDescription": "Description",
|
||||
"EditListingWizard.tabLabelLocation": "Location",
|
||||
"EditListingWizard.tabLabelPhotos": "Photos",
|
||||
"EditListingWizard.tabLabelPolicy": "Sauna rules",
|
||||
"EditListingWizard.tabLabelPricing": "Pricing",
|
||||
"EmailVerificationForm.finishAccountSetup": "We will need to send you email notifications. To allow this, please verify your email address {email}.",
|
||||
"EmailVerificationForm.successButtonText": "Continue exploring",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue