Fetch available time slots for listing page

This commit is contained in:
Hannu Lyytikainen 2018-07-17 13:50:10 +03:00
parent 1b96549962
commit e3cfa970ad
3 changed files with 74 additions and 1 deletions

View file

@ -1,4 +1,5 @@
import pick from 'lodash/pick';
import moment from 'moment';
import config from '../../config';
import { types as sdkTypes } from '../../util/sdkLoader';
import { storableError } from '../../util/errors';
@ -21,6 +22,10 @@ export const FETCH_REVIEWS_REQUEST = 'app/ListingPage/FETCH_REVIEWS_REQUEST';
export const FETCH_REVIEWS_SUCCESS = 'app/ListingPage/FETCH_REVIEWS_SUCCESS';
export const FETCH_REVIEWS_ERROR = 'app/ListingPage/FETCH_REVIEWS_ERROR';
export const FETCH_TIME_SLOTS_REQUEST = 'app/ListingPage/FETCH_TIME_SLOTS_REQUEST';
export const FETCH_TIME_SLOTS_SUCCESS = 'app/ListingPage/FETCH_TIME_SLOTS_SUCCESS';
export const FETCH_TIME_SLOTS_ERROR = 'app/ListingPage/FETCH_TIME_SLOTS_ERROR';
export const SEND_ENQUIRY_REQUEST = 'app/ListingPage/SEND_ENQUIRY_REQUEST';
export const SEND_ENQUIRY_SUCCESS = 'app/ListingPage/SEND_ENQUIRY_SUCCESS';
export const SEND_ENQUIRY_ERROR = 'app/ListingPage/SEND_ENQUIRY_ERROR';
@ -32,6 +37,8 @@ const initialState = {
showListingError: null,
reviews: [],
fetchReviewsError: null,
timeSlots: [],
fetchTimesLotsError: null,
sendEnquiryInProgress: false,
sendEnquiryError: null,
enquiryModalOpenForListingId: null,
@ -55,6 +62,13 @@ const listingPageReducer = (state = initialState, action = {}) => {
case FETCH_REVIEWS_ERROR:
return { ...state, fetchReviewsError: payload };
case FETCH_TIME_SLOTS_REQUEST:
return { ...state, fetchTimeSlotsError: null };
case FETCH_TIME_SLOTS_SUCCESS:
return { ...state, timeSlots: payload };
case FETCH_TIME_SLOTS_ERROR:
return { ...state, fetchTimeSlotsError: payload };
case SEND_ENQUIRY_REQUEST:
return { ...state, sendEnquiryInProgress: true, sendEnquiryError: null };
case SEND_ENQUIRY_SUCCESS:
@ -95,6 +109,17 @@ export const fetchReviewsError = error => ({
payload: error,
});
export const fetchTimeSlotsRequest = () => ({ type: FETCH_TIME_SLOTS_REQUEST });
export const fetchTimeSlotsSuccess = timeSlots => ({
type: FETCH_TIME_SLOTS_SUCCESS,
payload: timeSlots,
});
export const fetchTimeSlotsError = error => ({
type: FETCH_TIME_SLOTS_ERROR,
error: true,
payload: error,
});
export const sendEnquiryRequest = () => ({ type: SEND_ENQUIRY_REQUEST });
export const sendEnquirySuccess = () => ({ type: SEND_ENQUIRY_SUCCESS });
export const sendEnquiryError = e => ({ type: SEND_ENQUIRY_ERROR, error: true, payload: e });
@ -143,6 +168,7 @@ export const showListing = (listingId, isOwn = false) => (dispatch, getState, sd
};
export const fetchReviews = listingId => (dispatch, getState, sdk) => {
dispatch(fetchReviewsRequest);
return sdk.reviews
.query({
listing_id: listingId,
@ -159,6 +185,19 @@ export const fetchReviews = listingId => (dispatch, getState, sdk) => {
});
};
export const fetchTimeSlots = params => (dispatch, getState, sdk) => {
dispatch(fetchTimeSlotsRequest);
return sdk.timeslots
.query(params)
.then(response => {
const timeSlots = denormalisedResponseEntities(response);
dispatch(fetchTimeSlotsSuccess(timeSlots));
})
.catch(e => {
dispatch(fetchTimeSlotsError(storableError(e)));
});
};
export const sendEnquiry = (listingId, message) => (dispatch, getState, sdk) => {
dispatch(sendEnquiryRequest());
const bodyParams = {
@ -190,5 +229,19 @@ export const loadData = (params, search) => dispatch => {
if (params.variant === LISTING_PAGE_PENDING_APPROVAL_VARIANT) {
return dispatch(showListing(listingId, true));
}
return Promise.all([dispatch(showListing(listingId)), dispatch(fetchReviews(listingId))]);
// fetch time slots for 90 days starting today
// as the booking can only be done for 90 days
// in the future due to Stripe limitations
const start = moment().toDate();
const end = moment()
.add(90, 'days')
.toDate();
const timeSlotsParams = { listingId, start, end };
return Promise.all([
dispatch(showListing(listingId)),
dispatch(fetchTimeSlots(timeSlotsParams)),
dispatch(fetchReviews(listingId)),
]);
};

View file

@ -497,6 +497,8 @@ ListingPageComponent.defaultProps = {
showListingError: null,
reviews: [],
fetchReviewsError: null,
timeSlots: [],
fetchTimeSlotsError: null,
sendEnquiryError: null,
categoriesConfig: config.custom.categories,
amenitiesConfig: config.custom.amenities,
@ -532,6 +534,8 @@ ListingPageComponent.propTypes = {
useInitialValues: func.isRequired,
reviews: arrayOf(propTypes.review),
fetchReviewsError: propTypes.error,
timeSlots: arrayOf(propTypes.timeSlot),
fetchTimeSlotsError: propTypes.error,
sendEnquiryInProgress: bool.isRequired,
sendEnquiryError: propTypes.error,
onSendEnquiry: func.isRequired,
@ -546,6 +550,8 @@ const mapStateToProps = state => {
showListingError,
reviews,
fetchReviewsError,
timeSlots,
fetchTimeSlotsError,
sendEnquiryInProgress,
sendEnquiryError,
enquiryModalOpenForListingId,
@ -574,6 +580,8 @@ const mapStateToProps = state => {
showListingError,
reviews,
fetchReviewsError,
timeSlots,
fetchTimeSlotsError,
sendEnquiryInProgress,
sendEnquiryError,
};

View file

@ -187,6 +187,16 @@ propTypes.booking = shape({
}),
});
// Denormalised time slot object
propTypes.timeSlot = shape({
id: propTypes.uuid.isRequired,
type: propTypes.value('timeSlot').isRequired,
attributes: shape({
end: instanceOf(Date).isRequired,
start: instanceOf(Date).isRequired,
}),
});
// When a customer makes a booking to a listing, a transaction is
// created with the initial request transition.
export const TRANSITION_REQUEST = 'transition/request';
@ -425,6 +435,7 @@ export const ERROR_CODE_EMAIL_NOT_VERIFIED = 'email-unverified';
export const ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS = 'email-too-many-verification-requests';
export const ERROR_CODE_UPLOAD_OVER_LIMIT = 'request-upload-over-limit';
export const ERROR_CODE_VALIDATION_INVALID_PARAMS = 'validation-invalid-params';
export const ERROR_CODE_VALIDATION_INVALID_VALUE = 'validation-invalid-value';
export const ERROR_CODE_NOT_FOUND = 'not-found';
export const ERROR_CODE_FORBIDDEN = 'forbidden';
export const ERROR_CODE_MISSING_STRIPE_ACCOUNT = 'transaction-missing-stripe-account';
@ -441,6 +452,7 @@ const ERROR_CODES = [
ERROR_CODE_TOO_MANY_VERIFICATION_REQUESTS,
ERROR_CODE_UPLOAD_OVER_LIMIT,
ERROR_CODE_VALIDATION_INVALID_PARAMS,
ERROR_CODE_VALIDATION_INVALID_VALUE,
ERROR_CODE_NOT_FOUND,
ERROR_CODE_FORBIDDEN,
ERROR_CODE_MISSING_STRIPE_ACCOUNT,