Add a wizard tab for editing listing features

This commit is contained in:
Hannu Lyytikainen 2018-01-29 11:25:13 +02:00
parent a7932134e1
commit bd598ccc54
6 changed files with 131 additions and 3 deletions

View file

@ -0,0 +1,98 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { FormattedMessage } from 'react-intl';
import { toPairs } from 'lodash';
import { ensureListing } from '../../util/data';
import { createSlug } from '../../util/urlHelpers';
import { EditListingFeaturesForm } from '../../containers';
import { NamedLink } from '../../components';
const EditListingFeaturesPanel = props => {
const {
rootClassName,
className,
listing,
onSubmit,
onChange,
submitButtonText,
panelUpdated,
updateInProgress,
errors,
} = props;
const classes = classNames(rootClassName || 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="EditListingLocationPanel.title" values={{ listingTitle: listingLink }} />
) : (
<FormattedMessage id="EditListingLocationPanel.createListingTitle" />
);
const currentFeaturesArray = publicData && publicData.amenities;
const currentFeatures =
currentFeaturesArray &&
currentFeaturesArray.reduce((map, key) => {
map[key] = true;
return map;
}, {});
return (
<div className={classes}>
<h1>{panelTitle}</h1>
<EditListingFeaturesForm
initialValues={currentFeatures}
onSubmit={values => {
const entries = toPairs(values);
const amenities = entries.filter(entry => entry[1] === true).map(entry => entry[0]);
const updatedValues = {
publicData: { amenities },
};
onSubmit(updatedValues);
}}
onChange={onChange}
saveActionMsg={submitButtonText}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
/>
</div>
);
};
EditListingFeaturesPanel.defaultProps = {
rootClassName: null,
className: null,
listing: null,
};
const { bool, func, object, string } = PropTypes;
EditListingFeaturesPanel.propTypes = {
rootClassName: string,
className: 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 EditListingFeaturesPanel;

View file

@ -9,6 +9,7 @@ import { NamedRedirect, Tabs } from '../../components';
import EditListingWizardTab, {
DESCRIPTION,
FEATURES,
POLICY,
LOCATION,
PRICING,
@ -18,7 +19,7 @@ import css from './EditListingWizard.css';
// TODO: PHOTOS panel needs to be the last one since it currently contains PayoutDetailsForm modal
// All the other panels can be reordered.
export const TABS = [DESCRIPTION, POLICY, LOCATION, PRICING, PHOTOS];
export const TABS = [DESCRIPTION, FEATURES, POLICY, LOCATION, PRICING, PHOTOS];
// Tabs are horizontal in small screens
const MAX_HORIZONTAL_NAV_SCREEN_WIDTH = 1023;
@ -27,6 +28,8 @@ const tabLabel = (intl, tab) => {
let key = null;
if (tab === DESCRIPTION) {
key = 'EditListingWizard.tabLabelDescription';
} else if (tab === FEATURES) {
key = 'EditListingWizard.tabLabelFeatures';
} else if (tab === POLICY) {
key = 'EditListingWizard.tabLabelPolicy';
} else if (tab === LOCATION) {
@ -55,6 +58,8 @@ const tabCompleted = (tab, listing) => {
switch (tab) {
case DESCRIPTION:
return !!(description && title);
case FEATURES:
return !!(publicData && publicData.amenities);
case POLICY:
return !!(publicData && typeof publicData.rules !== 'undefined');
case LOCATION:

View file

@ -7,6 +7,7 @@ import { ensureListing } from '../../util/data';
import { createResourceLocatorString } from '../../util/routes';
import {
EditListingDescriptionPanel,
EditListingFeaturesPanel,
EditListingLocationPanel,
EditListingPhotosPanel,
EditListingPoliciesPanel,
@ -16,13 +17,14 @@ import {
import css from './EditListingWizard.css';
export const DESCRIPTION = 'description';
export const FEATURES = 'features';
export const POLICY = 'policy';
export const LOCATION = 'location';
export const PRICING = 'pricing';
export const PHOTOS = 'photos';
// EditListingWizardTab component supports these tabs
export const SUPPORTED_TABS = [DESCRIPTION, POLICY, LOCATION, PRICING, PHOTOS];
export const SUPPORTED_TABS = [DESCRIPTION, FEATURES, POLICY, LOCATION, PRICING, PHOTOS];
const pathParamsToNextTab = (params, tab, marketplaceTabs) => {
const nextTabIndex = marketplaceTabs.findIndex(s => s === tab) + 1;
@ -104,6 +106,20 @@ const EditListingWizardTab = props => {
/>
);
}
case FEATURES: {
const submitButtonTranslationKey = isNew
? 'EditListingWizard.saveNewFeatures'
: 'EditListingWizard.saveEditFeatures';
return (
<EditListingFeaturesPanel
{...panelProps(FEATURES)}
submitButtonText={intl.formatMessage({ id: submitButtonTranslationKey })}
onSubmit={values => {
onCompleteEditListingWizardTab(tab, values);
}}
/>
);
}
case POLICY: {
const submitButtonTranslationKey = isNew
? 'EditListingWizard.saveNewPolicies'

View file

@ -16,6 +16,9 @@ export { default as Discussion } from './Discussion/Discussion';
export {
default as EditListingDescriptionPanel,
} from './EditListingDescriptionPanel/EditListingDescriptionPanel';
export {
default as EditListingFeaturesPanel,
} from './EditListingFeaturesPanel/EditListingFeaturesPanel';
export {
default as EditListingLocationPanel,
} from './EditListingLocationPanel/EditListingLocationPanel';

View file

@ -120,6 +120,8 @@
"EditListingDescriptionPanel.createListingTitle": "Add your sauna",
"EditListingDescriptionPanel.title": "Edit details of {listingTitle}",
"EditListingFeaturesForm.updateFailed": "Failed to update listing. Please try again.",
"EditListingFeaturesPanel.createListingTitle": "What amenities does your sauna have?",
"EditListingFeaturesPanel.title": "Edit the amenities of {listingTitle}",
"EditListingLocationForm.address": "Address",
"EditListingLocationForm.addressNotRecognized": "We didn't recognize this location. Please try another location.",
"EditListingLocationForm.addressPlaceholder": "123 Example Street",
@ -161,16 +163,19 @@
"EditListingPricingPanel.listingPriceCurrencyInvalid": "Listing currency is different from the marketplace currency. You cannot edit the price.",
"EditListingPricingPanel.title": "Edit the pricing of {listingTitle}",
"EditListingWizard.saveEditDescription": "Save description",
"EditListingWizard.saveEditFeatures": "Save amenities",
"EditListingWizard.saveEditLocation": "Save location",
"EditListingWizard.saveEditPhotos": "Save photos",
"EditListingWizard.saveEditPolicies": "Save rules",
"EditListingWizard.saveEditPricing": "Save pricing",
"EditListingWizard.saveNewDescription": "Next: Policies",
"EditListingWizard.saveNewDescription": "Next: Amenities",
"EditListingWizard.saveNewFeatures": "Next: Rules",
"EditListingWizard.saveNewLocation": "Next: Pricing",
"EditListingWizard.saveNewPhotos": "Publish listing",
"EditListingWizard.saveNewPolicies": "Next: location",
"EditListingWizard.saveNewPricing": "Next: Photos",
"EditListingWizard.tabLabelDescription": "Description",
"EditListingWizard.tabLabelFeatures": "Amenities",
"EditListingWizard.tabLabelLocation": "Location",
"EditListingWizard.tabLabelPhotos": "Photos",
"EditListingWizard.tabLabelPolicy": "Sauna rules",