diff --git a/src/components/EditListingLocationPanel/EditListingLocationPanel.css b/src/components/EditListingLocationPanel/EditListingLocationPanel.css
new file mode 100644
index 00000000..d452fbfb
--- /dev/null
+++ b/src/components/EditListingLocationPanel/EditListingLocationPanel.css
@@ -0,0 +1,6 @@
+.root {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
diff --git a/src/components/EditListingLocationPanel/EditListingLocationPanel.js b/src/components/EditListingLocationPanel/EditListingLocationPanel.js
new file mode 100644
index 00000000..c6da85da
--- /dev/null
+++ b/src/components/EditListingLocationPanel/EditListingLocationPanel.js
@@ -0,0 +1,50 @@
+import React, { PropTypes } from 'react';
+import classNames from 'classnames';
+import { FormattedMessage } from 'react-intl';
+import { EditListingLocationForm } from '../../containers';
+
+import css from './EditListingLocationPanel.css';
+
+const EditListingLocationPanel = props => {
+ const { className, rootClassName, listing, onSubmit } = props;
+
+ const rootClass = rootClassName || css.root;
+ const classes = classNames(rootClass, className);
+ const { attributes: { address, geolocation } } = listing || { attributes: {} };
+
+ // Only render current search if full place object is available in the URL params
+ // TODO bounds and country are missing - those need to be queried directly from Google Places
+ const locationFieldsPresent = address && geolocation;
+ const initialSearchFormValues = {
+ location: locationFieldsPresent
+ ? {
+ search: address,
+ selectedPlace: { address, origin: geolocation },
+ }
+ : null,
+ };
+
+ return (
+
+
+
+
+ );
+};
+
+const { func, object, string } = PropTypes;
+
+EditListingLocationPanel.defaultProps = {
+ className: null,
+ rootClassName: null,
+ listing: null,
+};
+
+EditListingLocationPanel.propTypes = {
+ className: string,
+ rootClassName: string,
+ listing: object, // TODO Should be propTypes.listing after API support is added.
+ onSubmit: func.isRequired,
+};
+
+export default EditListingLocationPanel;
diff --git a/src/components/index.js b/src/components/index.js
index 65149f99..7070c72a 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -8,6 +8,7 @@ import CurrencyInput from './CurrencyInput/CurrencyInput';
import DateInput from './DateInput/DateInput';
import Discussion from './Discussion/Discussion';
import EditListingDescriptionPanel from './EditListingDescriptionPanel/EditListingDescriptionPanel';
+import EditListingLocationPanel from './EditListingLocationPanel/EditListingLocationPanel';
import EditListingWizard from './EditListingWizard/EditListingWizard';
import ExternalLink from './ExternalLink/ExternalLink';
import FilterPanel from './FilterPanel/FilterPanel';
@@ -50,6 +51,7 @@ export {
DateInput,
Discussion,
EditListingDescriptionPanel,
+ EditListingLocationPanel,
EditListingWizard,
ExternalLink,
FilterPanel,
diff --git a/src/containers/EditListingLocationForm/EditListingLocationForm.css b/src/containers/EditListingLocationForm/EditListingLocationForm.css
new file mode 100644
index 00000000..e3d80601
--- /dev/null
+++ b/src/containers/EditListingLocationForm/EditListingLocationForm.css
@@ -0,0 +1,10 @@
+.root {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+
+.submitButton {
+ margin-top: 1rem;
+}
diff --git a/src/containers/EditListingLocationForm/EditListingLocationForm.example.js b/src/containers/EditListingLocationForm/EditListingLocationForm.example.js
new file mode 100644
index 00000000..08955f3a
--- /dev/null
+++ b/src/containers/EditListingLocationForm/EditListingLocationForm.example.js
@@ -0,0 +1,11 @@
+/* eslint-disable no-console */
+import EditListingLocationForm from './EditListingLocationForm';
+
+export const Empty = {
+ component: EditListingLocationForm,
+ props: {
+ onSubmit: values => {
+ console.log('Submit EditListingLocationForm with (unformatted) values:', values);
+ },
+ },
+};
diff --git a/src/containers/EditListingLocationForm/EditListingLocationForm.js b/src/containers/EditListingLocationForm/EditListingLocationForm.js
new file mode 100644
index 00000000..aba33637
--- /dev/null
+++ b/src/containers/EditListingLocationForm/EditListingLocationForm.js
@@ -0,0 +1,98 @@
+import React, { Component, PropTypes } from 'react';
+import { compose } from 'redux';
+import { connect } from 'react-redux';
+import { Field, reduxForm, formValueSelector, propTypes as formPropTypes } from 'redux-form';
+import { intlShape, injectIntl } from 'react-intl';
+import * as propTypes from '../../util/propTypes';
+import { enhancedField } from '../../util/forms';
+import { autocompleteSearchRequired, autocompletePlaceSelected } from '../../util/validators';
+import { LocationAutocompleteInput, Button } from '../../components';
+
+import css from './EditListingLocationForm.css';
+
+export class EditListingLocationFormComponent extends Component {
+ constructor(props) {
+ super(props);
+
+ // We must create the enhanced components outside the render function
+ // to avoid losing focus.
+ // See: https://github.com/erikras/redux-form/releases/tag/v6.0.0-alpha.14
+ this.EnhancedLocationAutocompleteInput = enhancedField(LocationAutocompleteInput);
+ }
+
+ render() {
+ const {
+ disabled,
+ handleSubmit,
+ intl,
+ invalid,
+ saveActionMsg,
+ submitting,
+ } = this.props;
+
+ const titleRequiredMessage = intl.formatMessage({ id: 'EditListingLocationForm.location' });
+ const locationRequiredMessage = intl.formatMessage({
+ id: 'EditListingLocationForm.locationRequired',
+ });
+ const locationNotRecognizedMessage = intl.formatMessage({
+ id: 'EditListingLocationForm.locationNotRecognized',
+ });
+
+ return (
+
+ );
+ }
+}
+
+EditListingLocationFormComponent.defaultProps = {
+ saveActionMsg: 'Next: pricing',
+ selectedPlace: null,
+};
+
+const { func, string } = PropTypes;
+
+EditListingLocationFormComponent.propTypes = {
+ ...formPropTypes,
+ intl: intlShape.isRequired,
+ onSubmit: func.isRequired,
+ saveActionMsg: string,
+ selectedPlace: propTypes.place,
+};
+
+const formName = 'EditListingLocationForm';
+
+// When a field depends on the value of another field, we must connect
+// to the store and select the required values to inject to the
+// component.
+//
+// See: http://redux-form.com/6.6.1/examples/selectingFormValues/
+const selector = formValueSelector(formName);
+const mapStateToProps = state => {
+ const location = selector(state, 'location');
+ return {
+ selectedPlace: location && location.selectedPlace ? location.selectedPlace : null,
+ };
+};
+
+export default compose(connect(mapStateToProps), reduxForm({ form: formName }), injectIntl)(
+ EditListingLocationFormComponent
+);
diff --git a/src/containers/EditListingLocationForm/EditListingLocationForm.test.js b/src/containers/EditListingLocationForm/EditListingLocationForm.test.js
new file mode 100644
index 00000000..eb52664e
--- /dev/null
+++ b/src/containers/EditListingLocationForm/EditListingLocationForm.test.js
@@ -0,0 +1,21 @@
+// TODO: 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 { EditListingLocationFormComponent } from './EditListingLocationForm';
+
+const noop = () => null;
+
+describe('EditListingLocationForm', () => {
+ it('matches snapshot', () => {
+ const tree = renderShallow(
+ v}
+ />
+ );
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/containers/EditListingLocationForm/__snapshots__/EditListingLocationForm.test.js.snap b/src/containers/EditListingLocationForm/__snapshots__/EditListingLocationForm.test.js.snap
new file mode 100644
index 00000000..73370bea
--- /dev/null
+++ b/src/containers/EditListingLocationForm/__snapshots__/EditListingLocationForm.test.js.snap
@@ -0,0 +1,22 @@
+exports[`EditListingLocationForm matches snapshot 1`] = `
+
+`;
diff --git a/src/containers/index.js b/src/containers/index.js
index 5f89165c..2306f6e7 100644
--- a/src/containers/index.js
+++ b/src/containers/index.js
@@ -5,6 +5,7 @@ import ChangePasswordForm from './ChangePasswordForm/ChangePasswordForm';
import CheckoutPage from './CheckoutPage/CheckoutPage';
import ContactDetailsPage from './ContactDetailsPage/ContactDetailsPage';
import EditListingDescriptionForm from './EditListingDescriptionForm/EditListingDescriptionForm';
+import EditListingLocationForm from './EditListingLocationForm/EditListingLocationForm';
import EditListingPage from './EditListingPage/EditListingPage';
import EditProfilePage from './EditProfilePage/EditProfilePage';
import SearchForm from './SearchForm/SearchForm';
@@ -36,6 +37,7 @@ export {
CheckoutPage,
ContactDetailsPage,
EditListingDescriptionForm,
+ EditListingLocationForm,
EditListingPage,
EditProfilePage,
SearchForm,
diff --git a/src/examples.js b/src/examples.js
index c33f2603..e5ad79ef 100644
--- a/src/examples.js
+++ b/src/examples.js
@@ -25,6 +25,8 @@ import * as ChangeAccountPasswordForm
import * as ChangePasswordForm from './containers/ChangePasswordForm/ChangePasswordForm.example';
import * as EditListingDescriptionForm
from './containers/EditListingDescriptionForm/EditListingDescriptionForm.example';
+import * as EditListingLocationForm
+ from './containers/EditListingLocationForm/EditListingLocationForm.example';
import * as SearchForm from './containers/SearchForm/SearchForm.example';
import * as LoginForm from './containers/LoginForm/LoginForm.example';
import * as PasswordForgottenForm
@@ -42,6 +44,7 @@ export {
CurrencyInput,
DateInput,
EditListingDescriptionForm,
+ EditListingLocationForm,
EditListingWizard,
ListingCard,
LocationAutocompleteInput,
diff --git a/src/translations/en.json b/src/translations/en.json
index f3ee77da..dab5288e 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -39,6 +39,10 @@
"EditListingDescriptionForm.titlePlaceholder": "What's the name of your sauna?",
"EditListingDescriptionForm.titleRequired": "You need to add a name.",
"EditListingDescriptionPanel.title": "Add your sauna",
+ "EditListingLocationForm.location": "Location",
+ "EditListingLocationForm.locationRequired": "You need to provide a location",
+ "EditListingLocationForm.locationNotRecognized": "We didn't recognize this location. Please try another location.",
+ "EditListingLocationPanel.title": "Where's your sauna located?",
"EditListingPage.titleCreateListing": "Create a listing",
"EditListingPage.titleEditListing": "Edit listing",
"HeroSection.subTitle": "The largest online community to rent music studios",