diff --git a/src/components/BookingPanel/BookingPanel.example.js b/src/components/BookingPanel/BookingPanel.example.js
index 589027c148..5cabada42e 100644
--- a/src/components/BookingPanel/BookingPanel.example.js
+++ b/src/components/BookingPanel/BookingPanel.example.js
@@ -9,7 +9,7 @@ export const Default = {
props: {
className: css.example,
listing: createListing('listing_1'),
- handleBookingSubmit: values => console.log('Submit:', values),
+ onSubmit: values => console.log('Submit:', values),
title: Booking title,
subTitle: 'Hosted by Author N',
authorDisplayName: 'Author Name',
@@ -22,7 +22,7 @@ export const WithClosedListing = {
props: {
className: css.example,
listing: createListing('listing_1', { state: LISTING_STATE_CLOSED }),
- handleBookingSubmit: values => console.log('Submit:', values),
+ onSubmit: values => console.log('Submit:', values),
title: Booking title,
subTitle: 'Hosted by Author N',
authorDisplayName: 'Author Name',
diff --git a/src/components/BookingPanel/BookingPanel.js b/src/components/BookingPanel/BookingPanel.js
index bec513b007..eed0d224a2 100644
--- a/src/components/BookingPanel/BookingPanel.js
+++ b/src/components/BookingPanel/BookingPanel.js
@@ -55,7 +55,7 @@ const BookingPanel = props => {
listing,
isOwnListing,
unitType,
- handleBookingSubmit,
+ onSubmit,
title,
subTitle,
authorDisplayName,
@@ -107,7 +107,7 @@ const BookingPanel = props => {
className={css.bookingForm}
submitButtonWrapperClassName={css.bookingDatesSubmitButtonWrapper}
unitType={unitType}
- onSubmit={handleBookingSubmit}
+ onSubmit={onSubmit}
price={price}
isOwnListing={isOwnListing}
timeSlots={timeSlots}
@@ -158,7 +158,7 @@ BookingPanel.propTypes = {
listing: propTypes.listing.isRequired,
isOwnListing: bool,
unitType: propTypes.bookingUnitType,
- handleBookingSubmit: func.isRequired,
+ onSubmit: func.isRequired,
title: oneOfType([object, string]).isRequired,
subTitle: oneOfType([object, string]),
authorDisplayName: string.isRequired,
diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js
index 463b83b4c0..691bdacca9 100644
--- a/src/components/TransactionPanel/TransactionPanel.helpers.js
+++ b/src/components/TransactionPanel/TransactionPanel.helpers.js
@@ -182,6 +182,7 @@ export const BookingPanelMaybe = props => {
listingTitle,
subTitle,
provider,
+ onSubmit,
onManageDisableScrolling,
timeSlots,
fetchTimeSlotsError,
@@ -201,6 +202,7 @@ export const BookingPanelMaybe = props => {
title={listingTitle}
subTitle={subTitle}
authorDisplayName={authorDisplayName}
+ onSubmit={onSubmit}
onManageDisableScrolling={onManageDisableScrolling}
timeSlots={timeSlots}
fetchTimeSlotsError={fetchTimeSlotsError}
diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js
index 8e736c2aa0..db6a235777 100644
--- a/src/components/TransactionPanel/TransactionPanel.js
+++ b/src/components/TransactionPanel/TransactionPanel.js
@@ -131,6 +131,7 @@ export class TransactionPanelComponent extends Component {
declineInProgress,
acceptSaleError,
declineSaleError,
+ onSubmitBookingRequest,
timeSlots,
fetchTimeSlotsError,
} = this.props;
@@ -330,6 +331,7 @@ export class TransactionPanelComponent extends Component {
listingTitle={listingTitle}
subTitle={bookingSubTitle}
provider={currentProvider}
+ onSubmit={onSubmitBookingRequest}
onManageDisableScrolling={onManageDisableScrolling}
timeSlots={timeSlots}
fetchTimeSlotsError={fetchTimeSlotsError}
@@ -394,6 +396,7 @@ TransactionPanelComponent.propTypes = {
onShowMoreMessages: func.isRequired,
onSendMessage: func.isRequired,
onSendReview: func.isRequired,
+ onSubmitBookingRequest: func.isRequired,
timeSlots: arrayOf(propTypes.timeSlot),
fetchTimeSlotsError: propTypes.error,
diff --git a/src/components/TransactionPanel/TransactionPanel.test.js b/src/components/TransactionPanel/TransactionPanel.test.js
index 1b4faa091a..b3443d0a69 100644
--- a/src/components/TransactionPanel/TransactionPanel.test.js
+++ b/src/components/TransactionPanel/TransactionPanel.test.js
@@ -108,6 +108,7 @@ describe('TransactionPanel - Sale', () => {
onSendMessage: noop,
onSendReview: noop,
onResetForm: noop,
+ onSubmitBookingRequest: noop,
intl: fakeIntl,
};
@@ -276,6 +277,7 @@ describe('TransactionPanel - Order', () => {
onDeclineSale: noop,
acceptInProgress: false,
declineInProgress: false,
+ onSubmitBookingRequest: noop,
};
it('enquired matches snapshot', () => {
diff --git a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap
index d8098efc67..cac213d58c 100644
--- a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap
+++ b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap
@@ -1031,6 +1031,7 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -2349,6 +2350,7 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -3667,6 +3669,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -4985,6 +4988,7 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -6303,6 +6307,7 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -7621,6 +7626,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -8939,6 +8945,7 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -10257,6 +10264,7 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -11575,6 +11583,7 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -12893,6 +12902,7 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -14211,6 +14221,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -15529,6 +15540,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -16847,6 +16859,7 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
@@ -18165,6 +18178,7 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = `
}
listingTitle="listing1 title"
onManageDisableScrolling={[Function]}
+ onSubmit={[Function]}
provider={
Object {
"attributes": Object {
diff --git a/src/containers/CheckoutPage/CheckoutPage.duck.js b/src/containers/CheckoutPage/CheckoutPage.duck.js
index 5cb8a10b7f..059d1bc159 100644
--- a/src/containers/CheckoutPage/CheckoutPage.duck.js
+++ b/src/containers/CheckoutPage/CheckoutPage.duck.js
@@ -27,6 +27,7 @@ const initialState = {
speculateTransactionInProgress: false,
speculateTransactionError: null,
speculatedTransaction: null,
+ enquiredTransaction: null,
initiateOrderError: null,
};
diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js
index 4b3d8d63c5..b2ba4cdfda 100644
--- a/src/containers/CheckoutPage/CheckoutPage.js
+++ b/src/containers/CheckoutPage/CheckoutPage.js
@@ -75,7 +75,14 @@ export class CheckoutPageComponent extends Component {
* based on this initial data.
*/
loadInitialData() {
- const { bookingData, bookingDates, listing, fetchSpeculatedTransaction, history } = this.props;
+ const {
+ bookingData,
+ bookingDates,
+ listing,
+ enquiredTransaction,
+ fetchSpeculatedTransaction,
+ history,
+ } = this.props;
// Browser's back navigation should not rewrite data in session store.
// Action is 'POP' on both history.back() and page refresh cases.
// Action is 'PUSH' when user has directed through a link
@@ -85,12 +92,12 @@ export class CheckoutPageComponent extends Component {
const hasDataInProps = !!(bookingData && bookingDates && listing) && hasNavigatedThroughLink;
if (hasDataInProps) {
// Store data only if data is passed through props and user has navigated through a link.
- storeData(bookingData, bookingDates, listing, STORAGE_KEY);
+ storeData(bookingData, bookingDates, listing, enquiredTransaction, STORAGE_KEY);
}
// NOTE: stored data can be empty if user has already successfully completed transaction.
const pageData = hasDataInProps
- ? { bookingData, bookingDates, listing }
+ ? { bookingData, bookingDates, listing, enquiredTransaction }
: storedData(STORAGE_KEY);
const hasData =
@@ -465,6 +472,7 @@ CheckoutPageComponent.defaultProps = {
bookingDates: null,
speculateTransactionError: null,
speculatedTransaction: null,
+ enquiredTransaction: null,
currentUser: null,
};
@@ -480,6 +488,7 @@ CheckoutPageComponent.propTypes = {
speculateTransactionInProgress: bool.isRequired,
speculateTransactionError: propTypes.error,
speculatedTransaction: propTypes.transaction,
+ enquiredTransaction: propTypes.transaction,
initiateOrderError: propTypes.error,
currentUser: propTypes.currentUser,
params: shape({
@@ -508,6 +517,7 @@ const mapStateToProps = state => {
speculateTransactionInProgress,
speculateTransactionError,
speculatedTransaction,
+ enquiredTransaction,
initiateOrderError,
} = state.CheckoutPage;
const { currentUser } = state.user;
@@ -519,6 +529,7 @@ const mapStateToProps = state => {
speculateTransactionInProgress,
speculateTransactionError,
speculatedTransaction,
+ enquiredTransaction,
listing,
initiateOrderError,
};
diff --git a/src/containers/CheckoutPage/CheckoutPage.test.js b/src/containers/CheckoutPage/CheckoutPage.test.js
index a04fddb8af..5cfab905cf 100644
--- a/src/containers/CheckoutPage/CheckoutPage.test.js
+++ b/src/containers/CheckoutPage/CheckoutPage.test.js
@@ -59,6 +59,7 @@ describe('CheckoutPage', () => {
speculateTransactionError: null,
speculateTransactionInProgress: false,
speculatedTransaction: null,
+ enquiredTransaction: null,
};
it('should return the initial state', () => {
diff --git a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js
index 7195cb39f4..f45c826999 100644
--- a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js
+++ b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js
@@ -7,6 +7,7 @@
import moment from 'moment';
import reduce from 'lodash/reduce';
import { types as sdkTypes } from '../../util/sdkLoader';
+import { TRANSITION_ENQUIRE } from '../../util/types';
const { UUID, Money } = sdkTypes;
@@ -46,8 +47,20 @@ export const isValidListing = listing => {
return validateProperties(listing, props);
};
+// Validate content of an enquired transaction received from SessionStore.
+// An id is required and the last transition needs to be the enquire transition.
+export const isValidEnquiredTransaction = transaction => {
+ const props = {
+ id: id => id instanceof UUID,
+ attributes: v => {
+ return typeof v === 'string' && v.lastTransition === TRANSITION_ENQUIRE;
+ },
+ };
+ return validateProperties(transaction, props);
+};
+
// Stores given bookingDates and listing to sessionStorage
-export const storeData = (bookingData, bookingDates, listing, storageKey) => {
+export const storeData = (bookingData, bookingDates, listing, enquiredTransaction, storageKey) => {
if (window && window.sessionStorage && listing && bookingDates && bookingData) {
// TODO: How should we deal with Dates when data is serialized?
// Hard coded serializable date objects atm.
@@ -59,6 +72,7 @@ export const storeData = (bookingData, bookingDates, listing, storageKey) => {
bookingEnd: { date: bookingDates.bookingEnd, _serializedType: 'SerializableDate' },
},
listing,
+ enquiredTransaction,
storedAt: { date: new Date(), _serializedType: 'SerializableDate' },
};
/* eslint-enable no-underscore-dangle */
@@ -83,7 +97,7 @@ export const storedData = storageKey => {
return sdkTypes.reviver(k, v);
};
- const { bookingData, bookingDates, listing, storedAt } = checkoutPageData
+ const { bookingData, bookingDates, listing, enquiredTransaction, storedAt } = checkoutPageData
? JSON.parse(checkoutPageData, reviver)
: {};
@@ -92,8 +106,19 @@ export const storedData = storageKey => {
? moment(storedAt).isAfter(moment().subtract(1, 'days'))
: false;
- if (isFreshlySaved && isValidBookingDates(bookingDates) && isValidListing(listing)) {
- return { bookingData, bookingDates, listing };
+ // resolve enquired transaction as valid if it is missing
+ const isEnquiredTransactionValid = !!enquiredTransaction
+ ? isValidEnquiredTransaction(enquiredTransaction)
+ : true;
+
+ const isStoredDataValid =
+ isFreshlySaved &&
+ isValidBookingDates(bookingDates) &&
+ isValidListing(listing) &&
+ isEnquiredTransactionValid;
+
+ if (isStoredDataValid) {
+ return { bookingData, bookingDates, listing, enquiredTransaction };
}
}
return {};
diff --git a/src/containers/ListingPage/ListingPage.js b/src/containers/ListingPage/ListingPage.js
index 2d02d3a6e6..9fa61c00b7 100644
--- a/src/containers/ListingPage/ListingPage.js
+++ b/src/containers/ListingPage/ListingPage.js
@@ -441,7 +441,7 @@ export class ListingPageComponent extends Component {
listing={currentListing}
isOwnListing={isOwnListing}
unitType={unitType}
- handleBookingSubmit={handleBookingSubmit}
+ onSubmit={handleBookingSubmit}
title={bookingTitle}
subTitle={bookingSubTitle}
authorDisplayName={authorDisplayName}
diff --git a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
index 847f36678d..1962c361a1 100644
--- a/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
+++ b/src/containers/ListingPage/__snapshots__/ListingPage.test.js.snap
@@ -265,7 +265,6 @@ exports[`ListingPage matches snapshot 1`] = `
{
totalMessagePages,
oldestMessagePageFetched,
fetchTransactionError,
+ history,
intl,
messages,
onManageDisableScrolling,
@@ -66,10 +71,41 @@ export const TransactionPageComponent = props => {
onDeclineSale,
timeSlots,
fetchTimeSlotsError,
+ useInitialValues,
} = props;
const currentTransaction = ensureTransaction(transaction);
const currentListing = ensureListing(currentTransaction.listing);
+
+ const handleSubmitBookingRequest = values => {
+ const { bookingDates, ...bookingData } = values;
+
+ const initialValues = {
+ listing: currentListing,
+ enquiredTransaction: currentTransaction,
+ bookingData,
+ bookingDates: {
+ bookingStart: bookingDates.startDate,
+ bookingEnd: bookingDates.endDate,
+ },
+ };
+
+ const routes = routeConfiguration();
+ // Customize checkout page state with current listing and selected bookingDates
+ const { setInitialValues } = findRouteByRouteName('CheckoutPage', routes);
+ useInitialValues(setInitialValues, initialValues);
+
+ // Redirect to CheckoutPage
+ history.push(
+ createResourceLocatorString(
+ 'CheckoutPage',
+ routes,
+ { id: currentListing.id.uuid, slug: createSlug(currentListing.attributes.title) },
+ {}
+ )
+ );
+ };
+
const deletedListingTitle = intl.formatMessage({
id: 'TransactionPage.deletedListing',
});
@@ -160,6 +196,7 @@ export const TransactionPageComponent = props => {
declineInProgress={declineInProgress}
acceptSaleError={acceptSaleError}
declineSaleError={declineSaleError}
+ onSubmitBookingRequest={handleSubmitBookingRequest}
timeSlots={timeSlots}
fetchTimeSlotsError={fetchTimeSlotsError}
/>
@@ -226,6 +263,15 @@ TransactionPageComponent.propTypes = {
onSendMessage: func.isRequired,
timeSlots: arrayOf(propTypes.timeSlot),
fetchTimeSlotsError: propTypes.error,
+ useInitialValues: func.isRequired,
+
+ // from withRouter
+ history: shape({
+ push: func.isRequired,
+ }).isRequired,
+ location: shape({
+ search: string,
+ }).isRequired,
// from injectIntl
intl: intlShape.isRequired,
@@ -291,10 +337,12 @@ const mapDispatchToProps = dispatch => {
dispatch(manageDisableScrolling(componentId, disableScrolling)),
onSendReview: (role, tx, reviewRating, reviewContent) =>
dispatch(sendReview(role, tx, reviewRating, reviewContent)),
+ useInitialValues: (setInitialValues, values) => dispatch(setInitialValues(values)),
};
};
const TransactionPage = compose(
+ withRouter,
connect(
mapStateToProps,
mapDispatchToProps
diff --git a/src/containers/TransactionPage/TransactionPage.test.js b/src/containers/TransactionPage/TransactionPage.test.js
index e62e6d3c5a..ccec9181e8 100644
--- a/src/containers/TransactionPage/TransactionPage.test.js
+++ b/src/containers/TransactionPage/TransactionPage.test.js
@@ -38,6 +38,7 @@ describe('TransactionPage - Sale', () => {
onAcceptSale: noop,
onDeclineSale: noop,
scrollingDisabled: false,
+ useInitialValues: noop,
transaction,
totalMessages: 0,
totalMessagePages: 0,
@@ -48,6 +49,15 @@ describe('TransactionPage - Sale', () => {
onSendMessage: noop,
onResetForm: noop,
intl: fakeIntl,
+
+ location: {
+ pathname: `/sale/${txId}/details`,
+ search: '',
+ hash: '',
+ },
+ history: {
+ push: () => console.log('HistoryPush called'),
+ },
};
const tree = renderShallow();
@@ -82,6 +92,7 @@ describe('TransactionPage - Order', () => {
fetchMessagesInProgress: false,
sendMessageInProgress: false,
scrollingDisabled: false,
+ useInitialValues: noop,
transaction,
onShowMoreMessages: noop,
onSendMessage: noop,
@@ -92,6 +103,15 @@ describe('TransactionPage - Order', () => {
declineInProgress: false,
onAcceptSale: noop,
onDeclineSale: noop,
+
+ location: {
+ pathname: `/order/${txId}/details`,
+ search: '',
+ hash: '',
+ },
+ history: {
+ push: () => console.log('HistoryPush called'),
+ },
};
const tree = renderShallow();
diff --git a/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap b/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap
index 085bbbbbbf..53c4905035 100644
--- a/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap
+++ b/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap
@@ -56,6 +56,7 @@ exports[`TransactionPage - Order matches snapshot 1`] = `
onDeclineSale={[Function]}
onSendMessage={[Function]}
onShowMoreMessages={[Function]}
+ onSubmitBookingRequest={[Function]}
sendMessageError={null}
sendMessageInProgress={false}
timeSlots={null}
@@ -254,6 +255,7 @@ exports[`TransactionPage - Sale matches snapshot 1`] = `
onDeclineSale={[Function]}
onSendMessage={[Function]}
onShowMoreMessages={[Function]}
+ onSubmitBookingRequest={[Function]}
sendMessageError={null}
sendMessageInProgress={false}
timeSlots={null}