Show available time slots in date input

This commit is contained in:
Hannu Lyytikainen 2018-07-23 19:56:31 +03:00
parent 0d14e447bd
commit d2a5f3f5f8
6 changed files with 67 additions and 4 deletions

View file

@ -199,7 +199,15 @@
color: var(--marketplaceColorDark);
border: 0;
}
& :global(.CalendarDay__blocked_out_of_range .renderedDay) {
/* Remove default bg-color and use our extra span instead '.renderedDay' */
& :global(.CalendarDay__blocked_calendar),
& :global(.CalendarDay__blocked_calendar:active),
& :global(.CalendarDay__blocked_calendar:hover) {
background-color: transparent;
color: var(--marketplaceColorDark);
border: 0;
}
& :global(.CalendarDay__blocked_out_of_range .CalendarDay__blocked_calendar .renderedDay) {
background-color: transparent;
}
& :global(.DateInput_fang) {

View file

@ -6,7 +6,12 @@
*/
import React, { Component } from 'react';
import { bool, func, instanceOf, shape, string } from 'prop-types';
import { SingleDatePicker, isInclusivelyAfterDay, isInclusivelyBeforeDay } from 'react-dates';
import {
SingleDatePicker,
isInclusivelyAfterDay,
isInclusivelyBeforeDay,
isSameDay,
} from 'react-dates';
import { intlShape, injectIntl } from 'react-intl';
import classNames from 'classnames';
import moment from 'moment';
@ -143,6 +148,7 @@ class DateInputComponent extends Component {
value,
children,
render,
timeSlots,
...datePickerProps
} = this.props;
/* eslint-enable no-unused-vars */
@ -151,6 +157,12 @@ class DateInputComponent extends Component {
const date = value && value.date instanceof Date ? moment(value.date) : initialMoment;
const isDayBlocked = timeSlots
? day => {
return !timeSlots.find(timeSlot => isSameDay(day, moment(timeSlot.attributes.start)));
}
: null;
const placeholder = placeholderText || intl.formatMessage({ id: 'FieldDateInput.placeholder' });
const screenReaderInputText =
@ -180,6 +192,7 @@ class DateInputComponent extends Component {
placeholder={placeholder}
screenReaderInputMessage={screenReaderInputText}
phrases={{ closeDatePicker: closeDatePickerText, clearDate: clearDateText }}
isDayBlocked={isDayBlocked}
/>
</div>
);

View file

@ -4,8 +4,18 @@ import { Form as FinalForm, FormSpy } from 'react-final-form';
import moment from 'moment';
import { Button } from '../../components';
import { required, bookingDateRequired, composeValidators } from '../../util/validators';
import { createTimeSlots } from '../../util/test-data';
import FieldDateInput from './FieldDateInput';
const createAvailableTimeSlots = (dayCount, availableDayCount) => {
const slots = createTimeSlots(new Date(), dayCount);
const availableSlotIndices = Array.from({ length: availableDayCount }, () =>
Math.floor(Math.random() * dayCount)
);
return availableSlotIndices.sort().map(i => slots[i]);
};
const FormComponent = props => (
<FinalForm
{...props}
@ -54,6 +64,7 @@ export const Empty = {
label: 'Date',
placeholderText: moment().format('ddd, MMMM D'),
format: null,
timeSlots: createAvailableTimeSlots(90, 60),
validate: composeValidators(required('Required'), bookingDateRequired('Date is not valid')),
onBlur: () => console.log('onBlur called from DateInput props.'),
onFocus: () => console.log('onFocus called from DateInput props.'),

View file

@ -5,10 +5,11 @@
* you should convert value.date to start date and end date before submitting it to API
*/
import React, { Component } from 'react';
import { bool, object, string } from 'prop-types';
import { bool, object, string, arrayOf } from 'prop-types';
import { Field } from 'react-final-form';
import classNames from 'classnames';
import { ValidationError } from '../../components';
import { propTypes } from '../../util/types';
import DateInput from './DateInput';
import css from './FieldDateInput.css';
@ -77,6 +78,7 @@ FieldDateInputComponent.defaultProps = {
id: null,
label: null,
placeholderText: null,
timeSlots: [],
};
FieldDateInputComponent.propTypes = {
@ -86,6 +88,7 @@ FieldDateInputComponent.propTypes = {
id: string,
label: string,
placeholderText: string,
timeSlots: arrayOf(propTypes.timeSlot),
input: object.isRequired,
meta: object.isRequired,
};

View file

@ -497,7 +497,7 @@ ListingPageComponent.defaultProps = {
showListingError: null,
reviews: [],
fetchReviewsError: null,
timeSlots: [],
timeSlots: null,
fetchTimeSlotsError: null,
sendEnquiryError: null,
categoriesConfig: config.custom.categories,

View file

@ -1,4 +1,5 @@
import Decimal from 'decimal.js';
import moment from 'moment';
import { types as sdkTypes } from './sdkLoader';
import { nightsBetween } from '../util/dates';
import {
@ -212,6 +213,33 @@ export const createReview = (id, attributes = {}, includes = {}) => {
};
};
/**
* Creates an array of time slot objects.
*
* @param {Date} startDate date when the time slots start
* @param {Number} numberOfDays number of time slots to create
*
* @return {Array} array of time slots
*/
export const createTimeSlots = (startDate, numberOfDays) => {
const startTime = moment(startDate).startOf('day');
return Array.from({ length: numberOfDays }, (v, i) => i).map(i => {
return {
id: new UUID(i),
type: 'timeSlot',
attributes: {
start: moment(startTime)
.add(i, 'days')
.toDate(),
end: moment(startTime)
.add(i + 1, 'days')
.toDate(),
},
};
});
};
// Default config for currency formatting in tests and examples.
export const currencyConfig = {
style: 'currency',