import React, { Component } from 'react';
import { string, bool, arrayOf } from 'prop-types';
import { compose } from 'redux';
import { Form as FinalForm } from 'react-final-form';
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
import classNames from 'classnames';
import moment from 'moment';
import { required, bookingDatesRequired, composeValidators } from '../../util/validators';
import { START_DATE, END_DATE } from '../../util/dates';
import { propTypes } from '../../util/types';
import config from '../../config';
import { Form, PrimaryButton, FieldDateRangeInput } from '../../components';
import EstimatedBreakdownMaybe from './EstimatedBreakdownMaybe';
import css from './BookingDatesForm.css';
export class BookingDatesFormComponent extends Component {
constructor(props) {
super(props);
this.state = { focusedInput: null };
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.onFocusedInputChange = this.onFocusedInputChange.bind(this);
}
// Function that can be passed to nested components
// so that they can notify this component when the
// focused input changes.
onFocusedInputChange(focusedInput) {
this.setState({ focusedInput });
}
// In case start or end date for the booking is missing
// focus on that input, otherwise continue with the
// default handleSubmit function.
handleFormSubmit(e) {
const { startDate, endDate } = e.bookingDates || {};
if (!startDate) {
e.preventDefault();
this.setState({ focusedInput: START_DATE });
} else if (!endDate) {
e.preventDefault();
this.setState({ focusedInput: END_DATE });
} else {
this.props.onSubmit(e);
}
}
render() {
const { rootClassName, className, price: unitPrice, ...rest } = this.props;
const classes = classNames(rootClassName || css.root, className);
if (!unitPrice) {
return (
);
}
if (unitPrice.currency !== config.currency) {
return (
);
}
return (
{
const {
endDatePlaceholder,
startDatePlaceholder,
form,
handleSubmit,
intl,
isOwnListing,
submitButtonWrapperClassName,
unitPrice,
unitType,
values,
timeSlots,
fetchTimeSlotsError,
} = fieldRenderProps;
const { startDate, endDate } = values && values.bookingDates ? values.bookingDates : {};
const bookingStartLabel = intl.formatMessage({
id: 'BookingDatesForm.bookingStartTitle',
});
const bookingEndLabel = intl.formatMessage({ id: 'BookingDatesForm.bookingEndTitle' });
const requiredMessage = intl.formatMessage({ id: 'BookingDatesForm.requiredDate' });
const startDateErrorMessage = intl.formatMessage({
id: 'FieldDateRangeInput.invalidStartDate',
});
const endDateErrorMessage = intl.formatMessage({
id: 'FieldDateRangeInput.invalidEndDate',
});
const timeSlotsError = fetchTimeSlotsError ? (
) : null;
// This is the place to collect breakdown estimation data. See the
// EstimatedBreakdownMaybe component to change the calculations
// for customized payment processes.
const bookingData =
startDate && endDate
? {
unitType,
unitPrice,
startDate,
endDate,
// NOTE: If unitType is `line-item/units`, a new picker
// for the quantity should be added to the form.
quantity: 1,
}
: null;
const bookingInfo = bookingData ? (
) : null;
const dateFormatOptions = {
weekday: 'short',
month: 'short',
day: 'numeric',
};
const now = moment();
const today = now.startOf('day').toDate();
const tomorrow = now
.startOf('day')
.add(1, 'days')
.toDate();
const startDatePlaceholderText =
startDatePlaceholder || intl.formatDate(today, dateFormatOptions);
const endDatePlaceholderText =
endDatePlaceholder || intl.formatDate(tomorrow, dateFormatOptions);
const submitButtonClasses = classNames(
submitButtonWrapperClassName || css.submitButtonWrapper
);
return (
);
}}
/>
);
}
}
BookingDatesFormComponent.defaultProps = {
rootClassName: null,
className: null,
submitButtonWrapperClassName: null,
price: null,
isOwnListing: false,
startDatePlaceholder: null,
endDatePlaceholder: null,
timeSlots: null,
};
BookingDatesFormComponent.propTypes = {
rootClassName: string,
className: string,
submitButtonWrapperClassName: string,
unitType: propTypes.bookingUnitType.isRequired,
price: propTypes.money,
isOwnListing: bool,
timeSlots: arrayOf(propTypes.timeSlot),
// from injectIntl
intl: intlShape.isRequired,
// for tests
startDatePlaceholder: string,
endDatePlaceholder: string,
};
const BookingDatesForm = compose(injectIntl)(BookingDatesFormComponent);
BookingDatesForm.displayName = 'BookingDatesForm';
export default BookingDatesForm;