diff --git a/src/components/BookingInfo/BookingInfo.css b/src/components/BookingInfo/BookingInfo.css
new file mode 100644
index 00000000..214777e4
--- /dev/null
+++ b/src/components/BookingInfo/BookingInfo.css
@@ -0,0 +1,18 @@
+.container {
+ display: flex;
+ flex-direction: column;
+}
+
+.row {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.totalDivider {
+ width: 100%;
+}
+
+.totalPrice {
+ font-weight: bold;
+}
diff --git a/src/components/BookingInfo/BookingInfo.example.js b/src/components/BookingInfo/BookingInfo.example.js
index b20ac3ff..9797d6ca 100644
--- a/src/components/BookingInfo/BookingInfo.example.js
+++ b/src/components/BookingInfo/BookingInfo.example.js
@@ -1,12 +1,11 @@
-/* eslint-disable import/prefer-default-export */
+import { types } from '../../util/sdkLoader';
import BookingInfo from './BookingInfo';
export const Empty = {
component: BookingInfo,
props: {
- pricePerDay: '55\u20AC',
- bookingPeriod: 'Jan 2nd - Jan 4th',
- bookingDuration: '3 days',
- total: '165\u20AC',
+ unitPrice: new types.Money(10, 'USD'),
+ bookingStart: new Date('Fri, 14 Apr 2017 GMT'),
+ bookingEnd: new Date('Sun, 16 Apr 2017 GMT'),
},
};
diff --git a/src/components/BookingInfo/BookingInfo.js b/src/components/BookingInfo/BookingInfo.js
index 1fec2bc1..9cb8124b 100644
--- a/src/components/BookingInfo/BookingInfo.js
+++ b/src/components/BookingInfo/BookingInfo.js
@@ -1,32 +1,91 @@
+/**
+ * This component will show the booking info and calculated total price.
+ * I.e. dates and other details related to payment decision in receipt format.
+ */
import React, { PropTypes } from 'react';
+import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
+import Decimal from 'decimal.js';
+import moment from 'moment';
+import classNames from 'classnames';
+import config from '../../config';
+import { convertMoneyToNumber } from '../../util/currency';
+import { types } from '../../util/sdkLoader';
+import css from './BookingInfo.css';
+
+const BookingInfoComponent = props => {
+ const { bookingStart, bookingEnd, className, intl, unitPrice } = props;
+
+ const hasSelectedDays = bookingStart && bookingEnd;
+ const bookingPeriod = hasSelectedDays
+ ?
+ : '';
+ const nightCount = hasSelectedDays ? moment(bookingEnd).diff(moment(bookingStart), 'days') : null;
+ const nightCountMessage = nightCount
+ ?
+ : null;
+
+ const priceAsNumber = convertMoneyToNumber(unitPrice, config.currencyConfig.subUnitDivisor);
+ const formattedPrice = intl.formatNumber(priceAsNumber, config.currencyConfig);
+ const totalPriceAsNumber = hasSelectedDays
+ ? new Decimal(priceAsNumber).times(nightCount).toNumber()
+ : null;
+ const formattedTotalPrice = hasSelectedDays
+ ? intl.formatNumber(totalPriceAsNumber, config.currencyConfig)
+ : null;
-const BookingInfo = props => {
- const { pricePerDay, bookingPeriod, bookingDuration, total } = props;
return (
-
- -
- Price per day:
-
- - {pricePerDay}
- -
- Booking period:
-
- - {`${bookingPeriod}, ${bookingDuration}`}
- -
- Total
-
- - {total}
-
+
+
+
+
+
+
+ {formattedPrice}
+
+
+
+
+
+
+ {bookingPeriod}
+
+
+ {nightCountMessage}
+
+
+
+
+
+
+
+
+ {formattedTotalPrice}
+
+
+
);
};
-const { string } = PropTypes;
+BookingInfoComponent.defaultProps = { bookingStart: null, bookingEnd: null, className: '' };
-BookingInfo.propTypes = {
- pricePerDay: string.isRequired,
- bookingPeriod: string.isRequired,
- bookingDuration: string.isRequired,
- total: string.isRequired,
+const { instanceOf, string } = PropTypes;
+
+BookingInfoComponent.propTypes = {
+ bookingStart: instanceOf(Date),
+ bookingEnd: instanceOf(Date),
+ className: string,
+ intl: intlShape.isRequired,
+ unitPrice: instanceOf(types.Money).isRequired,
};
+const BookingInfo = injectIntl(BookingInfoComponent);
+
+BookingInfo.displayName = 'BookingInfo';
+
export default BookingInfo;
diff --git a/src/components/BookingInfo/BookingInfo.test.js b/src/components/BookingInfo/BookingInfo.test.js
index a5da72cc..d159d23d 100644
--- a/src/components/BookingInfo/BookingInfo.test.js
+++ b/src/components/BookingInfo/BookingInfo.test.js
@@ -1,15 +1,17 @@
import React from 'react';
+import { fakeIntl } from '../../util/test-data';
import { renderDeep } from '../../util/test-helpers';
+import { types } from '../../util/sdkLoader';
import BookingInfo from './BookingInfo';
describe('BookingInfo', () => {
it('matches snapshot', () => {
const tree = renderDeep(
);
expect(tree).toMatchSnapshot();
diff --git a/src/components/BookingInfo/__snapshots__/BookingInfo.test.js.snap b/src/components/BookingInfo/__snapshots__/BookingInfo.test.js.snap
index 67985c26..fa377ead 100644
--- a/src/components/BookingInfo/__snapshots__/BookingInfo.test.js.snap
+++ b/src/components/BookingInfo/__snapshots__/BookingInfo.test.js.snap
@@ -1,22 +1,52 @@
exports[`BookingInfo matches snapshot 1`] = `
-
- -
- Price per day:
-
- -
- 55\\\\u20AC
-
- -
- Booking period:
-
- -
- Jan 2nd - Jan 4th, 3 days
-
- -
- Total
-
- -
- 165\\u20AC
-
-
+
+
+
+
+ Price per day:
+
+
+
+ $10.00
+
+
+
+
+
+ Booking period:
+
+
+
+ 04/14/2017 - 04/16/2017
+
+
+
+
+ 2 days
+
+
+
+
+
+
+
+ Total:
+
+
+
+ $20.00
+
+
+
`;
diff --git a/src/components/CurrencyInput/CurrencyInput.example.js b/src/components/CurrencyInput/CurrencyInput.example.js
index f21bb246..fc3a89db 100644
--- a/src/components/CurrencyInput/CurrencyInput.example.js
+++ b/src/components/CurrencyInput/CurrencyInput.example.js
@@ -1,4 +1,3 @@
-/* eslint-disable import/prefer-default-export */
import React, { PropTypes } from 'react';
import { IntlProvider, addLocaleData } from 'react-intl';
import en from 'react-intl/locale-data/en';
diff --git a/src/components/DateInput/DateInput.example.js b/src/components/DateInput/DateInput.example.js
index df9ede29..716cf63b 100644
--- a/src/components/DateInput/DateInput.example.js
+++ b/src/components/DateInput/DateInput.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable import/prefer-default-export, no-console */
+/* eslint-disable no-console */
import React, { PropTypes } from 'react';
import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form';
import moment from 'moment';
diff --git a/src/components/DateInput/DateInput.js b/src/components/DateInput/DateInput.js
index 7ec67e04..01dac82f 100644
--- a/src/components/DateInput/DateInput.js
+++ b/src/components/DateInput/DateInput.js
@@ -3,10 +3,10 @@
* Styles for SingleDatePicker can be found from 'public/reactDates.css'.
* CSS modules can't handle global styles so they are currently added separately
*/
-import React, { PropTypes } from 'react';
-import momentPropTypes from 'react-moment-proptypes';
-import moment from 'moment';
+import React, { Component, PropTypes } from 'react';
+import { intlShape, injectIntl } from 'react-intl';
import { SingleDatePicker, isInclusivelyAfterDay } from 'react-dates';
+import moment from 'moment';
const HORIZONTAL_ORIENTATION = 'horizontal';
const ANCHOR_LEFT = 'left';
@@ -18,10 +18,10 @@ const defaultProps = {
// input related props
id: 'date',
- placeholder: 'Date',
+ placeholder: null, // Handled inside component
disabled: false,
- required: true,
- screenReaderInputMessage: '',
+ required: false,
+ screenReaderInputMessage: null, // Handled inside component
showClearDate: false,
// calendar presentation and interaction related props
@@ -52,12 +52,12 @@ const defaultProps = {
displayFormat: () => moment.localeData().longDateFormat('L'),
monthFormat: 'MMMM YYYY',
phrases: {
- closeDatePicker: 'Close',
- clearDate: 'Clear Date',
+ closeDatePicker: null, // Handled inside component
+ clearDate: null, // Handled inside component
},
};
-class DateInput extends React.Component {
+class DateInputComponent extends Component {
constructor(props) {
super(props);
this.state = {
@@ -69,7 +69,7 @@ class DateInput extends React.Component {
}
onDateChange(date) {
- this.props.onChange(date instanceof moment ? date.clone() : null);
+ this.props.onChange(date instanceof moment ? date.toDate() : null);
}
onFocusChange({ focused }) {
@@ -85,9 +85,34 @@ class DateInput extends React.Component {
render() {
const { focused } = this.state;
- // eslint-disable-next-line no-unused-vars
- const { initialDate, onBlur, onChange, onFocus, value, ...datePickerProps } = this.props;
- const date = value instanceof moment ? value.clone() : initialDate;
+ /* eslint-disable no-unused-vars */
+ const {
+ initialDate,
+ intl,
+ placeholder,
+ onBlur,
+ onChange,
+ onFocus,
+ phrases,
+ screenReaderInputMessage,
+ value,
+ ...datePickerProps
+ } = this.props;
+ /* eslint-enable no-unused-vars */
+
+ const initialMoment = initialDate ? moment(initialDate) : null;
+ const date = value instanceof Date ? moment(value) : initialMoment;
+
+ const placeholderText = placeholder ||
+ intl.formatMessage({ id: 'DateInput.defaultPlaceholder' });
+ const screenReaderInputText = screenReaderInputMessage ||
+ intl.formatMessage({ id: 'DateInput.screenReaderInputMessage' });
+ const closeDatePickerText = phrases.closeDatePicker
+ ? phrases.closeDatePicker
+ : intl.formatMessage({ id: 'DateInput.closeDatePicker' });
+ const clearDateText = phrases.clearDate
+ ? phrases.clearDate
+ : intl.formatMessage({ id: 'DateInput.clearDate' });
return (
@@ -98,23 +123,37 @@ class DateInput extends React.Component {
focused={focused}
onDateChange={this.onDateChange}
onFocusChange={this.onFocusChange}
+ placeholder={placeholderText}
+ screenReaderInputMessage={screenReaderInputText}
+ phrases={{ closeDatePicker: closeDatePickerText, clearDate: clearDateText }}
/>
);
}
}
-DateInput.defaultProps = defaultProps;
+DateInputComponent.defaultProps = defaultProps;
-const { func, string } = PropTypes;
+const { func, instanceOf, shape, string } = PropTypes;
-DateInput.propTypes = {
- initialDate: momentPropTypes.momentObj,
+DateInputComponent.propTypes = {
+ initialDate: instanceOf(Date),
+ intl: intlShape.isRequired,
+ isOutsideRange: func,
onChange: func.isRequired,
onBlur: func.isRequired,
onFocus: func.isRequired,
+ phrases: shape({
+ closeDatePicker: string,
+ clearDate: string,
+ }),
placeholder: string,
- value: momentPropTypes.momentObj,
+ screenReaderInputMessage: string,
+ value: instanceOf(Date),
};
+const DateInput = injectIntl(DateInputComponent);
+
+DateInput.displayName = 'DateInput';
+
export default DateInput;
diff --git a/src/components/DateInput/__snapshots__/DateInput.test.js.snap b/src/components/DateInput/__snapshots__/DateInput.test.js.snap
index 35012ac8..ca1778b2 100644
--- a/src/components/DateInput/__snapshots__/DateInput.test.js.snap
+++ b/src/components/DateInput/__snapshots__/DateInput.test.js.snap
@@ -8,8 +8,8 @@ exports[`DateInput matches snapshot 1`] = `
-
+
+ Date input
+
- Date
+ Date input
diff --git a/src/components/ListingCard/ListingCard.example.js b/src/components/ListingCard/ListingCard.example.js
index 9b739502..17511ed2 100644
--- a/src/components/ListingCard/ListingCard.example.js
+++ b/src/components/ListingCard/ListingCard.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import React from 'react';
import ListingCard from './ListingCard';
import { createUser, createListing, currencyConfig, fakeIntl } from '../../util/test-data';
diff --git a/src/components/ModalInMobile/ModalInMobile.example.js b/src/components/ModalInMobile/ModalInMobile.example.js
index b19caba4..f70d36c5 100644
--- a/src/components/ModalInMobile/ModalInMobile.example.js
+++ b/src/components/ModalInMobile/ModalInMobile.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import React, { Component } from 'react';
import { Button } from '../../components';
import ModalInMobile from './ModalInMobile';
diff --git a/src/components/NamedLink/NamedLink.example.js b/src/components/NamedLink/NamedLink.example.js
index afc54921..87d4816a 100644
--- a/src/components/NamedLink/NamedLink.example.js
+++ b/src/components/NamedLink/NamedLink.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import NamedLink from './NamedLink';
export const NamedLinkToSearchPage = {
diff --git a/src/components/OrderDetailsPanel/OrderDetailsPanel.js b/src/components/OrderDetailsPanel/OrderDetailsPanel.js
index 8c1fcdde..1823babb 100644
--- a/src/components/OrderDetailsPanel/OrderDetailsPanel.js
+++ b/src/components/OrderDetailsPanel/OrderDetailsPanel.js
@@ -1,5 +1,5 @@
import React, { PropTypes } from 'react';
-import { BookingInfo, NamedLink } from '../../components';
+import { NamedLink } from '../../components';
import css from './OrderDetailsPanel.css';
@@ -24,14 +24,13 @@ ContactInfo.propTypes = {
};
const OrderDetailsPanel = props => {
- const { className, orderId, title, imageUrl, info, contact, confirmationCode } = props;
+ const { className, orderId, title, imageUrl, contact, confirmationCode } = props;
return (
{title}
Confirmation code {confirmationCode}
-
Cancel booking
You have a new message!
@@ -47,7 +46,6 @@ OrderDetailsPanel.propTypes = {
orderId: oneOfType([string, number]).isRequired,
title: string.isRequired,
imageUrl: string.isRequired,
- info: object.isRequired,
contact: object.isRequired,
confirmationCode: string.isRequired,
};
diff --git a/src/components/OrderDetailsPanel/__snapshots__/OrderDetailsPanel.test.js.snap b/src/components/OrderDetailsPanel/__snapshots__/OrderDetailsPanel.test.js.snap
index 46780dd4..ccbf920c 100644
--- a/src/components/OrderDetailsPanel/__snapshots__/OrderDetailsPanel.test.js.snap
+++ b/src/components/OrderDetailsPanel/__snapshots__/OrderDetailsPanel.test.js.snap
@@ -20,11 +20,6 @@ exports[`OrderDetailsPanel matches snapshot 1`] = `
Confirmation code
some-test-confirmation-code
-
Cancel booking
diff --git a/src/components/index.js b/src/components/index.js
index c860eafd..61c1b777 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -2,6 +2,7 @@ import AddImages from './AddImages/AddImages';
import BookingInfo from './BookingInfo/BookingInfo';
import Button from './Button/Button';
import CurrencyInput from './CurrencyInput/CurrencyInput';
+import DateInput from './DateInput/DateInput';
import Discussion from './Discussion/Discussion';
import FilterPanel from './FilterPanel/FilterPanel';
import HeroSection from './HeroSection/HeroSection';
@@ -30,6 +31,7 @@ export {
BookingInfo,
Button,
CurrencyInput,
+ DateInput,
Discussion,
FilterPanel,
HeroSection,
diff --git a/src/containers/BookingDatesForm/BookingDatesForm.css b/src/containers/BookingDatesForm/BookingDatesForm.css
new file mode 100644
index 00000000..cb2ffee2
--- /dev/null
+++ b/src/containers/BookingDatesForm/BookingDatesForm.css
@@ -0,0 +1,23 @@
+.receipt {
+ margin-top: 1rem;
+ margin-bottom: 2rem;
+}
+
+.totalDivider {
+ width: 100%;
+}
+
+.totalPrice {
+ font-weight: bold;
+}
+
+.error {
+ color: red;
+ margin-top: 10px;
+ display: inline-block;
+}
+
+.smallPrint {
+ font-size: 12px;
+ text-align: center;
+}
diff --git a/src/containers/BookingDatesForm/BookingDatesForm.example.js b/src/containers/BookingDatesForm/BookingDatesForm.example.js
new file mode 100644
index 00000000..c1558b77
--- /dev/null
+++ b/src/containers/BookingDatesForm/BookingDatesForm.example.js
@@ -0,0 +1,13 @@
+/* eslint-disable no-console */
+import { types } from '../../util/sdkLoader';
+import BookingDatesForm from './BookingDatesForm';
+
+export const Empty = {
+ component: BookingDatesForm,
+ props: {
+ onSubmit: values => {
+ console.log('Submit BookingDatesForm with values:', values);
+ },
+ price: new types.Money(1099, 'USD'),
+ },
+};
diff --git a/src/containers/BookingDatesForm/BookingDatesForm.js b/src/containers/BookingDatesForm/BookingDatesForm.js
new file mode 100644
index 00000000..5ce80c37
--- /dev/null
+++ b/src/containers/BookingDatesForm/BookingDatesForm.js
@@ -0,0 +1,147 @@
+import React, { PropTypes } from 'react';
+import { compose } from 'redux';
+import { connect } from 'react-redux';
+import { Field, reduxForm, formValueSelector, propTypes as formPropTypes } from 'redux-form';
+import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
+import { isInclusivelyAfterDay, isInclusivelyBeforeDay } from 'react-dates';
+import moment from 'moment';
+import { types } from '../../util/sdkLoader';
+import { required } from '../../util/validators';
+import { Button, BookingInfo, DateInput } from '../../components';
+import css from './BookingDatesForm.css';
+
+const EnhancedDateInput = props => {
+ const { input, isOutsideRange, labelMessage, placeholder, meta } = props;
+ const { onBlur, onChange, onFocus, value } = input;
+ const { touched, error } = meta;
+ const maybeIsOutsideRange = isOutsideRange ? { isOutsideRange } : {};
+ const inputProps = { ...maybeIsOutsideRange, onBlur, onChange, onFocus, placeholder, value };
+
+ return (
+
+ {labelMessage ? : null}
+
+ {touched && error ? {error} : null}
+
+ );
+};
+
+EnhancedDateInput.defaultProps = {
+ input: null,
+ isOutsideRange: null,
+ labelMessage: null,
+ placeholder: 'Date',
+};
+
+const { bool, func, instanceOf, node, object, shape, string } = PropTypes;
+
+EnhancedDateInput.propTypes = {
+ input: object,
+ isOutsideRange: func,
+ labelMessage: node,
+ meta: shape({
+ touched: bool,
+ error: string,
+ }).isRequired,
+ placeholder: string,
+};
+
+export const BookingDatesFormComponent = props => {
+ const {
+ bookingStart,
+ bookingEnd,
+ className,
+ handleSubmit,
+ intl,
+ price,
+ pristine,
+ submitting,
+ } = props;
+ const placeholderText = intl.formatMessage({ id: 'BookingDatesForm.placeholder' });
+ const bookingStartLabel = intl.formatMessage({ id: 'BookingDatesForm.bookingStartTitle'});
+ const bookingEndLabel = intl.formatMessage({ id: 'BookingDatesForm.bookingEndTitle'});
+ const requiredMessage = intl.formatMessage({ id: 'BookingDatesForm.requiredDate' });
+
+ // A day is outside range if it is between today and booking end date (if end date has been chosen)
+ const isOutsideRangeStart = bookingEnd
+ ? {
+ isOutsideRange: day =>
+ !(isInclusivelyAfterDay(day, moment()) &&
+ isInclusivelyBeforeDay(day, moment(bookingEnd))),
+ }
+ : {};
+
+ // A day is outside range if it is after booking start date (or today if none is chosen)
+ const startOfBookingEndRange = bookingStart ? moment(bookingStart) : moment();
+ const isOutsideRangeEnd = bookingStart
+ ? { isOutsideRange: day => !isInclusivelyAfterDay(day, startOfBookingEndRange) }
+ : {};
+
+ const bookingInfo = price
+ ?
+ : null;
+
+ const invalid = !(bookingStart && bookingEnd);
+
+ return (
+
+ );
+};
+
+BookingDatesFormComponent.propTypes = {
+ ...formPropTypes,
+ intl: intlShape.isRequired,
+ price: instanceOf(types.Money).isRequired,
+};
+
+const formName = 'bookingDates';
+
+// 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 => {
+ return selector(state, 'bookingStart', 'bookingEnd');
+};
+
+const BookingDatesForm = compose(
+ connect(mapStateToProps),
+ reduxForm({ form: formName }),
+ injectIntl
+)(BookingDatesFormComponent);
+BookingDatesForm.displayName = 'BookingDatesForm';
+
+export default BookingDatesForm;
diff --git a/src/containers/BookingDatesForm/BookingDatesForm.test.js b/src/containers/BookingDatesForm/BookingDatesForm.test.js
new file mode 100644
index 00000000..72ba4fc0
--- /dev/null
+++ b/src/containers/BookingDatesForm/BookingDatesForm.test.js
@@ -0,0 +1,22 @@
+import React from 'react';
+import { types } from '../../util/sdkLoader';
+import { renderShallow } from '../../util/test-helpers';
+import { fakeIntl, fakeFormProps } from '../../util/test-data';
+import { BookingDatesFormComponent } from './BookingDatesForm';
+
+const noop = () => null;
+
+describe('BookingDatesForm', () => {
+ it('matches snapshot', () => {
+ const tree = renderShallow(
+ v}
+ price={new types.Money(1099, 'USD')}
+ />
+ );
+ expect(tree).toMatchSnapshot();
+ });
+});
diff --git a/src/containers/BookingDatesForm/__snapshots__/BookingDatesForm.test.js.snap b/src/containers/BookingDatesForm/__snapshots__/BookingDatesForm.test.js.snap
new file mode 100644
index 00000000..ea220fc4
--- /dev/null
+++ b/src/containers/BookingDatesForm/__snapshots__/BookingDatesForm.test.js.snap
@@ -0,0 +1,47 @@
+exports[`BookingDatesForm matches snapshot 1`] = `
+
+`;
diff --git a/src/containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example.js b/src/containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example.js
index 5e480a54..513d1ea8 100644
--- a/src/containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example.js
+++ b/src/containers/ChangeAccountPasswordForm/ChangeAccountPasswordForm.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import ChangeAccountPasswordForm from './ChangeAccountPasswordForm';
export const Empty = {
diff --git a/src/containers/ChangePasswordForm/ChangePasswordForm.example.js b/src/containers/ChangePasswordForm/ChangePasswordForm.example.js
index dbbc6b91..c7dd7703 100644
--- a/src/containers/ChangePasswordForm/ChangePasswordForm.example.js
+++ b/src/containers/ChangePasswordForm/ChangePasswordForm.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import ChangePasswordForm from './ChangePasswordForm';
export const Empty = {
diff --git a/src/containers/EditListingForm/EditListingForm.example.js b/src/containers/EditListingForm/EditListingForm.example.js
index ad22e0a7..c73352d6 100644
--- a/src/containers/EditListingForm/EditListingForm.example.js
+++ b/src/containers/EditListingForm/EditListingForm.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import EditListingForm from './EditListingForm';
export const Empty = {
diff --git a/src/containers/HeroSearchForm/HeroSearchForm.example.js b/src/containers/HeroSearchForm/HeroSearchForm.example.js
index 6f763010..623faf7c 100644
--- a/src/containers/HeroSearchForm/HeroSearchForm.example.js
+++ b/src/containers/HeroSearchForm/HeroSearchForm.example.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-console, import/prefer-default-export */
+/* eslint-disable no-console */
import HeroSearchForm from './HeroSearchForm';
export const Empty = {
diff --git a/src/containers/ListingPage/ListingPage.css b/src/containers/ListingPage/ListingPage.css
index fa6e4aaa..3eea1da6 100644
--- a/src/containers/ListingPage/ListingPage.css
+++ b/src/containers/ListingPage/ListingPage.css
@@ -67,7 +67,11 @@
background-color: #eee;
}
-.openDatePickerForm {
+.bookingForm {
+ margin: 0 1rem;
+}
+
+.openBookingForm {
position: fixed;
bottom: 0;
left: 0;
diff --git a/src/containers/ListingPage/ListingPage.js b/src/containers/ListingPage/ListingPage.js
index 9843212c..31ec6806 100644
--- a/src/containers/ListingPage/ListingPage.js
+++ b/src/containers/ListingPage/ListingPage.js
@@ -6,6 +6,7 @@ import config from '../../config';
import { types } from '../../util/sdkLoader';
import { convertMoneyToNumber } from '../../util/currency';
import { Button, Map, ModalInMobile, PageLayout } from '../../components';
+import { BookingDatesForm } from '../../containers';
import { getListingsById } from '../../ducks/sdk.duck';
import { showListing } from './ListingPage.duck';
import css from './ListingPage.css';
@@ -39,9 +40,22 @@ export class ListingPageComponent extends Component {
isBookingModalOpenOnMobile: tab && tab === 'book',
pageClassNames: '',
};
+
+ this.onSubmit = this.onSubmit.bind(this);
this.togglePageClassNames = this.togglePageClassNames.bind(this);
}
+ onSubmit(values) {
+ const { marketplaceData, params } = this.props;
+ const id = new UUID(params.id);
+ const listingsById = getListingsById(marketplaceData, [id]);
+ const currentListing = listingsById.length > 0 ? listingsById[0] : null;
+
+ this.setState({ isBookingModalOpenOnMobile: false });
+ // eslint-disable-next-line no-console
+ console.log('Submitting: bookedDates', values, 'and price', currentListing.attributes.price);
+ }
+
togglePageClassNames(className, addClass = true) {
this.setState(prevState => {
const prevPageClassNames = prevState.pageClassNames.split(' ');
@@ -116,10 +130,10 @@ export class ListingPageComponent extends Component {
title={bookBtnMessage}
togglePageClassNames={this.togglePageClassNames}
>
- ModalInMobile content
+
{map ? {map}
: null}
-
+
diff --git a/src/containers/ListingPage/ListingPage.test.js b/src/containers/ListingPage/ListingPage.test.js
index 8c76c2b1..b0ed9c03 100644
--- a/src/containers/ListingPage/ListingPage.test.js
+++ b/src/containers/ListingPage/ListingPage.test.js
@@ -11,14 +11,19 @@ const { UUID } = types;
describe('ListingPage', () => {
it('matches snapshot', () => {
const marketplaceData = { entities: { listing: { listing1: createListing('listing1') } } };
- const tree = renderShallow(
-
l}
- />
- );
+ const props = {
+ flattenedRoutes: [],
+ location: { search: '' },
+ history: {
+ push: () => console.log('HistoryPush called'),
+ },
+ params: { slug: 'listing1-title', id: 'listing1' },
+ marketplaceData,
+ intl: fakeIntl,
+ onLoadListing: () => {},
+ };
+
+ const tree = renderShallow();
expect(tree).toMatchSnapshot();
});
diff --git a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
index 762e291e..c6acbc7c 100644
--- a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
+++ b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
@@ -24,9 +24,14 @@ exports[`ListingPage matches snapshot 1`] = `
showAsModalMaxWidth={2500}
title="ListingPage.ctaButtonMessage"
togglePageClassNames={[Function]}>
-
- ModalInMobile content
-
+