diff --git a/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.css b/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.css
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.css
@@ -0,0 +1 @@
+
diff --git a/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.js b/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.js
new file mode 100644
index 00000000..9ee0f039
--- /dev/null
+++ b/src/components/EditListingFeaturesPanel/EditListingFeaturesPanel.js
@@ -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 ? (
+
+ {listingTitle}
+
+ ) : (
+ ''
+ );
+
+ const panelTitle = currentListing.id ? (
+
+ ) : (
+
+ );
+
+ const currentFeaturesArray = publicData && publicData.amenities;
+ const currentFeatures =
+ currentFeaturesArray &&
+ currentFeaturesArray.reduce((map, key) => {
+ map[key] = true;
+ return map;
+ }, {});
+
+ return (
+
+
{panelTitle}
+ {
+ 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}
+ />
+
+ );
+};
+
+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;
diff --git a/src/components/EditListingWizard/EditListingWizard.js b/src/components/EditListingWizard/EditListingWizard.js
index 0206f3bb..cf78c783 100644
--- a/src/components/EditListingWizard/EditListingWizard.js
+++ b/src/components/EditListingWizard/EditListingWizard.js
@@ -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:
diff --git a/src/components/EditListingWizard/EditListingWizardTab.js b/src/components/EditListingWizard/EditListingWizardTab.js
index 750c3851..d218972d 100644
--- a/src/components/EditListingWizard/EditListingWizardTab.js
+++ b/src/components/EditListingWizard/EditListingWizardTab.js
@@ -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 (
+ {
+ onCompleteEditListingWizardTab(tab, values);
+ }}
+ />
+ );
+ }
case POLICY: {
const submitButtonTranslationKey = isNew
? 'EditListingWizard.saveNewPolicies'
diff --git a/src/components/index.js b/src/components/index.js
index 9fa3a22e..1488e437 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -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';
diff --git a/src/translations/en.json b/src/translations/en.json
index aa562f0a..6cbdd521 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -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",