From 38b780827d1e566f5acf3a0e61800e507a06d95f Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 7 Dec 2018 14:58:44 +0200 Subject: [PATCH 01/15] Hide listing address link from provider --- src/components/TransactionPanel/TransactionPanel.css | 4 ---- .../TransactionPanel/TransactionPanel.helpers.js | 3 +-- src/components/TransactionPanel/TransactionPanel.js | 8 -------- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index 377ac04b2a..72f0ae9a86 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -202,10 +202,6 @@ margin-bottom: 37px; } } -.detailCardHeadingsProvider { - composes: detailCardHeadings; - margin-top: 24px; -} .detailCardTitle { margin-bottom: 10px; diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index b47c3fc989..e74f6814b0 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -89,7 +89,6 @@ export const FeedSection = props => { export const AddressLinkMaybe = props => { const { transaction, transactionRole, currentListing } = props; - const isProvider = transactionRole === 'provider'; const isCustomer = transactionRole === 'customer'; const txIsAcceptedForCustomer = isCustomer && txHasBeenAccepted(transaction); @@ -106,7 +105,7 @@ export const AddressLinkMaybe = props => { const fullAddress = typeof building === 'string' && building.length > 0 ? `${building}, ${address}` : address; - return (isProvider || txIsAcceptedForCustomer) && hrefToGoogleMaps ? ( + return txIsAcceptedForCustomer && hrefToGoogleMaps ? (

{fullAddress}

diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index 89fefc72c1..c55d291d07 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -321,14 +321,6 @@ export class TransactionPanelComponent extends Component { currentListing={currentListing} /> - ) : ( -
- -
)} {canShowActionButtons ? ( From 68f6eaa39144b640a28f1947749c1568ddc81edb Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Fri, 7 Dec 2018 15:04:10 +0200 Subject: [PATCH 02/15] Show BookingPanel on tx page Show the BookingPanel component on the tx page when the transaction has been started with an enquiry. --- .../TransactionPanel/TransactionPanel.css | 4 ++ .../TransactionPanel.helpers.js | 58 ++++++++++++++++--- .../TransactionPanel/TransactionPanel.js | 53 +++++++---------- 3 files changed, 76 insertions(+), 39 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index 72f0ae9a86..f80a233a05 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -404,3 +404,7 @@ top: 151px; } } + +.bookingPanel { + margin: 16px 48px 48px 48px; +} diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index e74f6814b0..123813539c 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -18,6 +18,7 @@ import { createSlug, stringify } from '../../util/urlHelpers'; import { ActivityFeed, BookingBreakdown, + BookingPanel, ExternalLink, NamedLink, PrimaryButton, @@ -151,16 +152,57 @@ const createListingLink = (listing, label, searchParams = {}, className = '') => } }; -// Functional component as a helper to build ActionButtons for -// provider when state is preauthorized -export const OrderActionButtonMaybe = props => { - const { className, rootClassName, canShowButtons, listing } = props; +// Functional component as a helper to build detail card headings +export const DetailCardHeadingsMaybe = props => { + const { authorDisplayName, transaction, transactionRole, listing, listingTitle } = props; - const title = ; - const listingLink = createListingLink(listing, title, { book: true }, css.requestToBookButton); - const classes = classNames(rootClassName || css.actionButtons, className); + const isCustomer = transactionRole === 'customer'; + const canShowDetailCardHeadings = isCustomer && !txIsEnquired(transaction); - return canShowButtons ?
{listingLink}
: null; + return canShowDetailCardHeadings ? ( +
+

{listingTitle}

+

+ +

+ +
+ ) : null; +}; + +// Functional component as a helper to build a BookingPanel +export const BookingPanelMaybe = props => { + const { + authorDisplayName, + transaction, + transactionRole, + listing, + listingTitle, + provider, + } = props; + + const isProviderLoaded = !!provider.id; + const isProviderBanned = isProviderLoaded && provider.attributes.banned; + const isCustomer = transactionRole === 'customer'; + const canShowBookingPanel = isCustomer && txIsEnquired(transaction) && !isProviderBanned; + + return canShowBookingPanel ? ( + console.log('submit')} + richTitle={listingTitle} + authorDisplayName={authorDisplayName} + onManageDisableScrolling={() => null} + timeSlots={null} + fetchTimeSlotsError={null} + /> + ) : null; }; // Functional component as a helper to build ActionButtons for diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index c55d291d07..945bb86484 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -1,8 +1,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { injectIntl, intlShape, FormattedMessage } from 'react-intl'; +import { injectIntl, intlShape } from 'react-intl'; import classNames from 'classnames'; -import { txIsEnquired, txIsRequested, propTypes } from '../../util/types'; +import { txIsRequested, propTypes } from '../../util/types'; import { ensureListing, ensureTransaction, ensureUser } from '../../util/data'; import { isMobileSafari } from '../../util/userAgent'; import { AvatarMedium, AvatarLarge, ResponsiveImage, ReviewModal } from '../../components'; @@ -11,9 +11,10 @@ import { SendMessageForm } from '../../forms'; // These are internal components that make this file more readable. import { AddressLinkMaybe, + BookingPanelMaybe, BreakdownMaybe, + DetailCardHeadingsMaybe, FeedSection, - OrderActionButtonMaybe, SaleActionButtonsMaybe, TransactionPageTitle, TransactionPageMessage, @@ -142,9 +143,6 @@ export class TransactionPanelComponent extends Component { const customerLoaded = !!currentCustomer.id; const isCustomerBanned = customerLoaded && currentCustomer.attributes.banned; const canShowSaleButtons = isProvider && txIsRequested(currentTransaction) && !isCustomerBanned; - const isProviderLoaded = !!currentProvider.id; - const isProviderBanned = isProviderLoaded && currentProvider.attributes.banned; - const canShowBookButton = isCustomer && txIsEnquired(currentTransaction) && !isProviderBanned; const bannedUserDisplayName = intl.formatMessage({ id: 'TransactionPanel.bannedUserDisplayName', @@ -168,7 +166,7 @@ export class TransactionPanelComponent extends Component { currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null; const actionButtonClasses = classNames(css.actionButtons); - const canShowActionButtons = canShowBookButton || canShowSaleButtons; + const canShowActionButtons = canShowSaleButtons; let actionButtons = null; if (canShowSaleButtons) { @@ -185,14 +183,6 @@ export class TransactionPanelComponent extends Component { onDeclineSale={onDeclineSale} /> ); - } else if (canShowBookButton) { - actionButtons = ( - - ); } const sendMessagePlaceholder = intl.formatMessage( @@ -306,23 +296,24 @@ export class TransactionPanelComponent extends Component { ) : null} - {isCustomer ? ( -
-

{listingTitle}

-

- -

- -
- )} + + + + {canShowActionButtons ? (
{actionButtons}
) : null} From a053a6c81a89031afb151a1f8c3e355432033518 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 10 Dec 2018 16:25:25 +0200 Subject: [PATCH 03/15] Fetch time slots on tx page --- .../TransactionPanel.helpers.js | 10 +- .../TransactionPanel/TransactionPanel.js | 8 + .../TransactionPanel.test.js.snap | 14486 +++++++++------- .../TransactionPage/TransactionPage.duck.js | 104 +- .../TransactionPage/TransactionPage.js | 12 + src/routeConfiguration.js | 4 +- 6 files changed, 8561 insertions(+), 6063 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index 123813539c..2e697cdb86 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -183,6 +183,8 @@ export const BookingPanelMaybe = props => { listing, listingTitle, provider, + timeSlots, + fetchTimeSlotsError, } = props; const isProviderLoaded = !!provider.id; @@ -193,14 +195,14 @@ export const BookingPanelMaybe = props => { return canShowBookingPanel ? ( console.log('submit')} - richTitle={listingTitle} + title={listingTitle} authorDisplayName={authorDisplayName} onManageDisableScrolling={() => null} - timeSlots={null} - fetchTimeSlotsError={null} + timeSlots={timeSlots} + fetchTimeSlotsError={fetchTimeSlotsError} /> ) : null; }; diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index 945bb86484..5b9a735c57 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -129,6 +129,8 @@ export class TransactionPanelComponent extends Component { declineInProgress, acceptSaleError, declineSaleError, + timeSlots, + fetchTimeSlotsError, } = this.props; const currentTransaction = ensureTransaction(transaction); @@ -311,6 +313,8 @@ export class TransactionPanelComponent extends Component { listing={currentListing} listingTitle={listingTitle} provider={currentProvider} + timeSlots={timeSlots} + fetchTimeSlotsError={fetchTimeSlotsError} /> @@ -346,6 +350,8 @@ TransactionPanelComponent.defaultProps = { initialMessageFailed: null, sendMessageError: null, sendReviewError: null, + timeSlots: null, + fetchTimeSlotsError: null, }; const { arrayOf, bool, func, number, string } = PropTypes; @@ -370,6 +376,8 @@ TransactionPanelComponent.propTypes = { onShowMoreMessages: func.isRequired, onSendMessage: func.isRequired, onSendReview: func.isRequired, + timeSlots: arrayOf(propTypes.timeSlot), + fetchTimeSlotsError: propTypes.error, // Sale related props onAcceptSale: func.isRequired, diff --git a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap index 57c63ef3a2..2f6f5ac982 100644 --- a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap +++ b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap @@ -849,160 +849,33 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` /> -
- -
- - - - - - -`; - -exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + +
+
+
+ + +`; + +exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+
+ + + +
+
+
+ +
+`; + +exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+
+ + + +
+
+
+ +
+`; + +exports[`TransactionPanel - Order declined matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+
+
+ +
+
+ + + +
+
+
+ +
+`; + +exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+
-
- + -
+ } + /> `; -exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` +exports[`TransactionPanel - Order enquired matches snapshot 1`] = `
@@ -2367,7 +6655,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/accept", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-01T00:00:00.000Z, "lineItems": Array [ Object { @@ -2448,7 +6736,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-canceled", + "uuid": "order-enquired", }, "listing": Object { "attributes": Object { @@ -2498,7 +6786,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/accept", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-01T00:00:00.000Z, "lineItems": Array [ Object { @@ -2579,7 +6867,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-canceled", + "uuid": "order-enquired", }, "listing": Object { "attributes": Object { @@ -2651,7 +6939,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/accept", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-01T00:00:00.000Z, "lineItems": Array [ Object { @@ -2732,7 +7020,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-canceled", + "uuid": "order-enquired", }, "listing": Object { "attributes": Object { @@ -2779,7 +7067,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/accept", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-01T00:00:00.000Z, "lineItems": Array [ Object { @@ -2860,7 +7148,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-canceled", + "uuid": "order-enquired", }, "listing": Object { "attributes": Object { @@ -2907,7 +7195,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/accept", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-01T00:00:00.000Z, "lineItems": Array [ Object { @@ -2988,7 +7276,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-canceled", + "uuid": "order-enquired", }, "listing": Object { "attributes": Object { @@ -3109,197 +7397,70 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` onOpenReviewModal={[Function]} onShowMoreMessages={[Function]} rootClassName="" - totalMessagePages={1} - /> - -
-
-
-
-
- -
-
-
- + +
+
+
+
+
+ + /> +
-
-
-
- -
-`; - -exports[`TransactionPanel - Order declined matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + - -
-
- -
+ } + /> +
+
+
+ +
+`; + +exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+
+ - -
-
-
-
-
- -
-
+ "provider": Object { + "attributes": Object { + "banned": false, + "profile": Object { + "abbreviatedName": "TT", + "displayName": "provider display name", + }, + }, + "id": UUID { + "uuid": "provider", + }, + "type": "user", + }, + "reviews": Array [], + "type": "transaction", + } + } + /> +
-
-
-
- -
-`; - -exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + /> +
-
-
- + +
+
+
+
+
+ + /> +
-
- - -
-
-
-
-
- -
-
-
- -
+ } + /> `; -exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` +exports[`TransactionPanel - Sale accepted matches snapshot 1`] = `
@@ -5805,8 +9287,8 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/enquire", - "lastTransitionedAt": 2017-06-01T00:00:00.000Z, + "lastTransition": "transition/accept", + "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { "code": "line-item/night", @@ -5831,12 +9313,12 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "provider", ], "lineTotal": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, "reversal": false, "unitPrice": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, }, @@ -5846,7 +9328,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "currency": "USD", }, "payoutTotal": Money { - "amount": 16400, + "amount": 15500, "currency": "USD", }, "transitions": Array [ @@ -5886,7 +9368,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-enquired", + "uuid": "sale-accepted", }, "listing": Object { "attributes": Object { @@ -5936,8 +9418,8 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/enquire", - "lastTransitionedAt": 2017-06-01T00:00:00.000Z, + "lastTransition": "transition/accept", + "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { "code": "line-item/night", @@ -5962,12 +9444,12 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "provider", ], "lineTotal": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, "reversal": false, "unitPrice": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, }, @@ -5977,7 +9459,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "currency": "USD", }, "payoutTotal": Money { - "amount": 16400, + "amount": 15500, "currency": "USD", }, "transitions": Array [ @@ -6017,7 +9499,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-enquired", + "uuid": "sale-accepted", }, "listing": Object { "attributes": Object { @@ -6089,8 +9571,8 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/enquire", - "lastTransitionedAt": 2017-06-01T00:00:00.000Z, + "lastTransition": "transition/accept", + "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { "code": "line-item/night", @@ -6115,12 +9597,12 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "provider", ], "lineTotal": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, "reversal": false, "unitPrice": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, }, @@ -6130,7 +9612,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "currency": "USD", }, "payoutTotal": Money { - "amount": 16400, + "amount": 15500, "currency": "USD", }, "transitions": Array [ @@ -6170,7 +9652,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-enquired", + "uuid": "sale-accepted", }, "listing": Object { "attributes": Object { @@ -6217,8 +9699,8 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/enquire", - "lastTransitionedAt": 2017-06-01T00:00:00.000Z, + "lastTransition": "transition/accept", + "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { "code": "line-item/night", @@ -6243,12 +9725,12 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "provider", ], "lineTotal": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, "reversal": false, "unitPrice": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, }, @@ -6258,7 +9740,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "currency": "USD", }, "payoutTotal": Money { - "amount": 16400, + "amount": 15500, "currency": "USD", }, "transitions": Array [ @@ -6298,7 +9780,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-enquired", + "uuid": "sale-accepted", }, "listing": Object { "attributes": Object { @@ -6345,8 +9827,8 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/enquire", - "lastTransitionedAt": 2017-06-01T00:00:00.000Z, + "lastTransition": "transition/accept", + "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { "code": "line-item/night", @@ -6371,12 +9853,12 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "provider", ], "lineTotal": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, "reversal": false, "unitPrice": Money { - "amount": -100, + "amount": -1000, "currency": "USD", }, }, @@ -6386,7 +9868,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "currency": "USD", }, "payoutTotal": Money { - "amount": 16400, + "amount": 15500, "currency": "USD", }, "transitions": Array [ @@ -6426,7 +9908,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "order-enquired", + "uuid": "sale-accepted", }, "listing": Object { "attributes": Object { @@ -6470,18 +9952,18 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` Object { "attributes": Object { "banned": false, - "email": "customer@example.com", + "email": "provider@example.com", "emailVerified": true, "profile": Object { - "abbreviatedName": "customer abbreviated name", - "displayName": "customer display name", - "firstName": "customer first name", - "lastName": "customer last name", + "abbreviatedName": "provider abbreviated name", + "displayName": "provider display name", + "firstName": "provider first name", + "lastName": "provider last name", }, "stripeConnected": true, }, "id": UUID { - "uuid": "customer", + "uuid": "provider", }, "type": "currentUser", } @@ -6545,200 +10027,73 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` } oldestMessagePageFetched={1} onOpenReviewModal={[Function]} - onShowMoreMessages={[Function]} - rootClassName="" - totalMessagePages={1} - /> - -
-
-
-
-
- -
-
-
- + +
+
+
+
+
+ + /> +
-
-
-
- -
-`; - -exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + - -
-
- -
+ } + /> +
+
+
+ +
+`; + +exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+
+ - -
-
-
-
- -
-
-
-
- -
-`; - -exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
+ +
+
+
+
+
+ +
+
+ - + -
-
- -
+ } + />
+
+
+ +
+`; + +exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+ - -
-
-
-
- -
-
-
-
- -
-`; - -exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
+ +
+
+
+
+
+ +
+
+ - + -
-
- -
+ } + />
+
+
+ +
+`; + +exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+ +
+ - -
-
-
-
- -
-
-
-
-
- -
-`; - -exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + /> +
-
-
- + +
+
+
+
+
+ + /> +
-
- + - -
-
-
-
-
- -
-
-
- -
+ } + /> `; -exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` +exports[`TransactionPanel - Sale delivered matches snapshot 1`] = `
@@ -11535,7 +14551,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/decline", + "lastTransition": "transition/complete", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -11616,7 +14632,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-declined", + "uuid": "sale-delivered", }, "listing": Object { "attributes": Object { @@ -11666,7 +14682,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/decline", + "lastTransition": "transition/complete", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -11747,7 +14763,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-declined", + "uuid": "sale-delivered", }, "listing": Object { "attributes": Object { @@ -11819,7 +14835,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/decline", + "lastTransition": "transition/complete", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -11900,7 +14916,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-declined", + "uuid": "sale-delivered", }, "listing": Object { "attributes": Object { @@ -11947,7 +14963,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/decline", + "lastTransition": "transition/complete", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -12028,7 +15044,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-declined", + "uuid": "sale-delivered", }, "listing": Object { "attributes": Object { @@ -12075,7 +15091,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/decline", + "lastTransition": "transition/complete", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -12156,7 +15172,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-declined", + "uuid": "sale-delivered", }, "listing": Object { "attributes": Object { @@ -12309,10 +15325,121 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` />
-
- + -
+ } + /> `; -exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` +exports[`TransactionPanel - Sale enquired matches snapshot 1`] = `
@@ -12681,7 +15867,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/complete", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -12762,7 +15948,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-delivered", + "uuid": "sale-enquired", }, "listing": Object { "attributes": Object { @@ -12812,7 +15998,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/complete", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -12893,7 +16079,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-delivered", + "uuid": "sale-enquired", }, "listing": Object { "attributes": Object { @@ -12965,7 +16151,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/complete", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -13046,7 +16232,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-delivered", + "uuid": "sale-enquired", }, "listing": Object { "attributes": Object { @@ -13093,7 +16279,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/complete", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -13174,7 +16360,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-delivered", + "uuid": "sale-enquired", }, "listing": Object { "attributes": Object { @@ -13221,7 +16407,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` Object { "attributes": Object { "createdAt": 2017-05-01T00:00:00.000Z, - "lastTransition": "transition/complete", + "lastTransition": "transition/enquire", "lastTransitionedAt": 2017-06-10T00:00:00.000Z, "lineItems": Array [ Object { @@ -13302,7 +16488,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "id": UUID { - "uuid": "sale-delivered", + "uuid": "sale-enquired", }, "listing": Object { "attributes": Object { @@ -13416,204 +16602,77 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` "type": "user", }, "type": "message", - }, - ] - } - oldestMessagePageFetched={1} - onOpenReviewModal={[Function]} - onShowMoreMessages={[Function]} - rootClassName="" - totalMessagePages={1} - /> - -
-
-
-
-
- -
-
-
- + +
+
+
+
+
+ + /> +
-
-
-
- -
-`; - -exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + - -
-
- -
+ } + /> +
+
+
+ +
+`; + +exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` +
+
+
+
+
+ +
+
+
+
+ - -
-
-
-
- -
-
-
-
-
- -
-`; - -exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` -
-
-
-
-
- -
-
-
- -
- + /> +
-
-
- + +
+
+
+
+
+ + /> +
-
- - -
-
-
-
-
- -
-
-
- -
+ } + /> ({ type: SEND_REVIEW_REQUEST }); const sendReviewSuccess = () => ({ type: SEND_REVIEW_SUCCESS }); const sendReviewError = e => ({ type: SEND_REVIEW_ERROR, error: true, payload: e }); +const fetchTimeSlotsRequest = () => ({ type: FETCH_TIME_SLOTS_REQUEST }); +const fetchTimeSlotsSuccess = timeSlots => ({ + type: FETCH_TIME_SLOTS_SUCCESS, + payload: timeSlots, +}); +const fetchTimeSlotsError = e => ({ + type: FETCH_TIME_SLOTS_ERROR, + error: true, + payload: e, +}); + // ================ Thunks ================ // const listingRelationship = txResponse => { return txResponse.data.data.relationships.listing.data; }; -export const fetchTransaction = id => (dispatch, getState, sdk) => { +export const fetchTransaction = (id, txRole) => (dispatch, getState, sdk) => { dispatch(fetchTransactionRequest()); let txResponse = null; @@ -234,11 +261,23 @@ export const fetchTransaction = id => (dispatch, getState, sdk) => { const listingId = listingRelationship(response).id; const entities = updatedEntities({}, response.data); const listingRef = { id: listingId, type: 'listing' }; - const denormalised = denormalisedEntities(entities, [listingRef]); + const transactionRef = { id, type: 'transaction' }; + const denormalised = denormalisedEntities(entities, [listingRef, transactionRef]); const listing = denormalised[0]; + const transaction = denormalised[1]; - const canFetchListing = listing && listing.attributes && !listing.attributes.deleted; + // Fetch time slots for transactions that are in enquired state + const canFetchTimeslots = + txRole === 'customer' && + config.fetchAvailableTimeSlots && + transaction && + txIsEnquired(transaction); + + if (canFetchTimeslots) { + dispatch(fetchTimeSlots(listingId)); + } + const canFetchListing = listing && listing.attributes && !listing.attributes.deleted; if (canFetchListing) { return sdk.listings.show({ id: listingId, @@ -475,12 +514,69 @@ const isNonEmpty = value => { return typeof value === 'object' || Array.isArray(value) ? !isEmpty(value) : !!value; }; +const timeSlotsRequest = params => (dispatch, getState, sdk) => { + return sdk.timeslots.query(params).then(response => { + return denormalisedResponseEntities(response); + }); +}; + +const fetchTimeSlots = listingId => (dispatch, getState, sdk) => { + dispatch(fetchTimeSlotsRequest); + + // Time slots can be fetched for 90 days at a time, + // for at most 180 days from now. If max number of bookable + // day exceeds 90, a second request is made. + + const maxTimeSlots = 90; + // booking range: today + bookable days -1 + const bookingRange = config.dayCountAvailableForBooking - 1; + const timeSlotsRange = Math.min(bookingRange, maxTimeSlots); + + const start = moment + .utc() + .startOf('day') + .toDate(); + const end = moment() + .utc() + .startOf('day') + .add(timeSlotsRange, 'days') + .toDate(); + const params = { listingId, start, end }; + + return dispatch(timeSlotsRequest(params)) + .then(timeSlots => { + const secondRequest = bookingRange > maxTimeSlots; + + if (secondRequest) { + const secondRange = Math.min(maxTimeSlots, bookingRange - maxTimeSlots); + const secondParams = { + listingId, + start: end, + end: moment(end) + .add(secondRange, 'days') + .toDate(), + }; + + return dispatch(timeSlotsRequest(secondParams)).then(secondBatch => { + const combined = timeSlots.concat(secondBatch); + dispatch(fetchTimeSlotsSuccess(combined)); + }); + } else { + dispatch(fetchTimeSlotsSuccess(timeSlots)); + } + }) + .catch(e => { + dispatch(fetchTimeSlotsError(storableError(e))); + }); +}; + // loadData is a collection of async calls that need to be made // before page has all the info it needs to render itself export const loadData = params => (dispatch, getState) => { const txId = new UUID(params.id); const state = getState().TransactionPage; const txRef = state.transactionRef; + const txRole = params.transactionRole; // In case a transaction reference is found from a previous // data load -> clear the state. Otherwise keep the non-null @@ -489,5 +585,5 @@ export const loadData = params => (dispatch, getState) => { dispatch(setInitialValues(initialValues)); // Sale / order (i.e. transaction entity in API) - return Promise.all([dispatch(fetchTransaction(txId)), dispatch(fetchMessages(txId, 1))]); + return Promise.all([dispatch(fetchTransaction(txId, txRole)), dispatch(fetchMessages(txId, 1))]); }; diff --git a/src/containers/TransactionPage/TransactionPage.js b/src/containers/TransactionPage/TransactionPage.js index 0ba4a089e2..03e67b6ba9 100644 --- a/src/containers/TransactionPage/TransactionPage.js +++ b/src/containers/TransactionPage/TransactionPage.js @@ -64,6 +64,8 @@ export const TransactionPageComponent = props => { declineSaleError, onAcceptSale, onDeclineSale, + timeSlots, + fetchTimeSlotsError, } = props; const currentTransaction = ensureTransaction(transaction); @@ -158,6 +160,8 @@ export const TransactionPageComponent = props => { declineInProgress={declineInProgress} acceptSaleError={acceptSaleError} declineSaleError={declineSaleError} + timeSlots={timeSlots} + fetchTimeSlotsError={fetchTimeSlotsError} /> ) : ( loadingOrFailedFetching @@ -192,6 +196,8 @@ TransactionPageComponent.defaultProps = { fetchMessagesError: null, initialMessageFailedToTransaction: null, sendMessageError: null, + timeSlots: null, + fetchTimeSlotsError: null, }; const { bool, func, oneOf, shape, string, arrayOf, number } = PropTypes; @@ -218,6 +224,8 @@ TransactionPageComponent.propTypes = { sendMessageError: propTypes.error, onShowMoreMessages: func.isRequired, onSendMessage: func.isRequired, + timeSlots: arrayOf(propTypes.timeSlot), + fetchTimeSlotsError: propTypes.error, // from injectIntl intl: intlShape.isRequired, @@ -241,6 +249,8 @@ const mapStateToProps = state => { sendMessageError, sendReviewInProgress, sendReviewError, + timeSlots, + fetchTimeSlotsError, } = state.TransactionPage; const { currentUser } = state.user; @@ -266,6 +276,8 @@ const mapStateToProps = state => { sendMessageError, sendReviewInProgress, sendReviewError, + timeSlots, + fetchTimeSlotsError, }; }; diff --git a/src/routeConfiguration.js b/src/routeConfiguration.js index 17e367267c..283bc72a31 100644 --- a/src/routeConfiguration.js +++ b/src/routeConfiguration.js @@ -193,7 +193,7 @@ const routeConfiguration = () => { auth: true, authPage: 'LoginPage', component: props => , - loadData: TransactionPage.loadData, + loadData: params => TransactionPage.loadData({ ...params, transactionRole: 'customer' }), setInitialValues: TransactionPage.setInitialValues, }, { @@ -209,7 +209,7 @@ const routeConfiguration = () => { auth: true, authPage: 'LoginPage', component: props => , - loadData: TransactionPage.loadData, + loadData: params => TransactionPage.loadData({ ...params, transactionRole: 'provider' }), }, { path: '/listings', From 5fe0ac3d4736e7c7d59527216105b487c089e748 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 10 Dec 2018 18:10:39 +0200 Subject: [PATCH 04/15] Add onManageDisableScrolling to BookingPanel --- .../TransactionPanel/TransactionPanel.helpers.js | 3 ++- .../TransactionPanel/TransactionPanel.js | 1 + .../__snapshots__/TransactionPanel.test.js.snap | 14 ++++++++++++++ .../__snapshots__/TransactionPage.test.js.snap | 4 ++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index 2e697cdb86..6dba6daf10 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -183,6 +183,7 @@ export const BookingPanelMaybe = props => { listing, listingTitle, provider, + onManageDisableScrolling, timeSlots, fetchTimeSlotsError, } = props; @@ -200,7 +201,7 @@ export const BookingPanelMaybe = props => { handleBookingSubmit={() => console.log('submit')} title={listingTitle} authorDisplayName={authorDisplayName} - onManageDisableScrolling={() => null} + onManageDisableScrolling={onManageDisableScrolling} timeSlots={timeSlots} fetchTimeSlotsError={fetchTimeSlotsError} /> diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index 5b9a735c57..84989a6b80 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -313,6 +313,7 @@ export class TransactionPanelComponent extends Component { listing={currentListing} listingTitle={listingTitle} provider={currentProvider} + onManageDisableScrolling={onManageDisableScrolling} timeSlots={timeSlots} fetchTimeSlotsError={fetchTimeSlotsError} /> diff --git a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap index 2f6f5ac982..c5e89f94b5 100644 --- a/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap +++ b/src/components/TransactionPanel/__snapshots__/TransactionPanel.test.js.snap @@ -1030,6 +1030,7 @@ exports[`TransactionPanel - Order accepted matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -2346,6 +2347,7 @@ exports[`TransactionPanel - Order autodeclined matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -3662,6 +3664,7 @@ exports[`TransactionPanel - Order canceled matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -4978,6 +4981,7 @@ exports[`TransactionPanel - Order declined matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -6294,6 +6298,7 @@ exports[`TransactionPanel - Order delivered matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -7610,6 +7615,7 @@ exports[`TransactionPanel - Order enquired matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -8926,6 +8932,7 @@ exports[`TransactionPanel - Order preauthorized matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -10242,6 +10249,7 @@ exports[`TransactionPanel - Sale accepted matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -11558,6 +11566,7 @@ exports[`TransactionPanel - Sale autodeclined matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -12874,6 +12883,7 @@ exports[`TransactionPanel - Sale canceled matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -14190,6 +14200,7 @@ exports[`TransactionPanel - Sale declined matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -15506,6 +15517,7 @@ exports[`TransactionPanel - Sale delivered matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -16822,6 +16834,7 @@ exports[`TransactionPanel - Sale enquired matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { @@ -18138,6 +18151,7 @@ exports[`TransactionPanel - Sale preauthorized matches snapshot 1`] = ` } } listingTitle="listing1 title" + onManageDisableScrolling={[Function]} provider={ Object { "attributes": Object { diff --git a/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap b/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap index c969f6a5c1..085bbbbbbf 100644 --- a/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap +++ b/src/containers/TransactionPage/__snapshots__/TransactionPage.test.js.snap @@ -48,6 +48,7 @@ exports[`TransactionPage - Order matches snapshot 1`] = ` declineSaleError={null} fetchMessagesError={null} fetchMessagesInProgress={false} + fetchTimeSlotsError={null} initialMessageFailed={false} messages={Array []} oldestMessagePageFetched={0} @@ -57,6 +58,7 @@ exports[`TransactionPage - Order matches snapshot 1`] = ` onShowMoreMessages={[Function]} sendMessageError={null} sendMessageInProgress={false} + timeSlots={null} totalMessagePages={0} transaction={ Object { @@ -244,6 +246,7 @@ exports[`TransactionPage - Sale matches snapshot 1`] = ` declineInProgress={false} declineSaleError={null} fetchMessagesError={null} + fetchTimeSlotsError={null} initialMessageFailed={false} messages={Array []} oldestMessagePageFetched={0} @@ -253,6 +256,7 @@ exports[`TransactionPage - Sale matches snapshot 1`] = ` onShowMoreMessages={[Function]} sendMessageError={null} sendMessageInProgress={false} + timeSlots={null} totalMessagePages={0} transaction={ Object { From a0d1984103ddbf2597f6f0dcb7bce25f65a99dcb Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 11 Dec 2018 11:43:26 +0200 Subject: [PATCH 05/15] Unify listing info sub titles --- .../TransactionPanel/TransactionPanel.css | 3 +- .../TransactionPanel.helpers.js | 8 ++-- .../TransactionPanel/TransactionPanel.js | 21 +++++++++- .../TransactionPanel.test.js.snap | 42 ++++++++++++------- src/translations/en.json | 4 +- src/translations/fr.json | 4 +- 6 files changed, 58 insertions(+), 24 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index f80a233a05..e1e8c44bb2 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -214,13 +214,12 @@ .detailCardSubtitle { @apply --marketplaceH5FontStyles; - color: var(--matterColorAnti); margin-top: 0; margin-bottom: 0; @media (--viewportLarge) { - margin-top: 1px; + margin-top: 9px; margin-bottom: 0; } } diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index 6dba6daf10..463b83b4c0 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -154,7 +154,7 @@ const createListingLink = (listing, label, searchParams = {}, className = '') => // Functional component as a helper to build detail card headings export const DetailCardHeadingsMaybe = props => { - const { authorDisplayName, transaction, transactionRole, listing, listingTitle } = props; + const { transaction, transactionRole, listing, listingTitle, subTitle } = props; const isCustomer = transactionRole === 'customer'; const canShowDetailCardHeadings = isCustomer && !txIsEnquired(transaction); @@ -162,9 +162,7 @@ export const DetailCardHeadingsMaybe = props => { return canShowDetailCardHeadings ? (

{listingTitle}

-

- -

+

{subTitle}

{ transactionRole, listing, listingTitle, + subTitle, provider, onManageDisableScrolling, timeSlots, @@ -200,6 +199,7 @@ export const BookingPanelMaybe = props => { listing={listing} handleBookingSubmit={() => console.log('submit')} title={listingTitle} + subTitle={subTitle} authorDisplayName={authorDisplayName} onManageDisableScrolling={onManageDisableScrolling} timeSlots={timeSlots} diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index 84989a6b80..8e736c2aa0 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -2,11 +2,13 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { injectIntl, intlShape } from 'react-intl'; import classNames from 'classnames'; -import { txIsRequested, propTypes } from '../../util/types'; +import { txIsRequested, LINE_ITEM_NIGHT, LINE_ITEM_DAY, propTypes } from '../../util/types'; import { ensureListing, ensureTransaction, ensureUser } from '../../util/data'; import { isMobileSafari } from '../../util/userAgent'; +import { formatMoney } from '../../util/currency'; import { AvatarMedium, AvatarLarge, ResponsiveImage, ReviewModal } from '../../components'; import { SendMessageForm } from '../../forms'; +import config from '../../config'; // These are internal components that make this file more readable. import { @@ -164,6 +166,20 @@ export class TransactionPanelComponent extends Component { ? deletedListingTitle : currentListing.attributes.title; + const unitType = config.bookingUnitType; + const isNightly = unitType === LINE_ITEM_NIGHT; + const isDaily = unitType === LINE_ITEM_DAY; + + const unitTranslationKey = isNightly + ? 'TransactionPanel.perNight' + : isDaily + ? 'TransactionPanel.perDay' + : 'TransactionPanel.perUnit'; + + const price = currentListing.attributes.price; + const formattedPrice = formatMoney(intl, price); + const bookingSubTitle = `${formattedPrice} ${intl.formatMessage({ id: unitTranslationKey })}`; + const firstImage = currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null; @@ -300,11 +316,11 @@ export class TransactionPanelComponent extends Component { ) : null}
Date: Wed, 12 Dec 2018 11:55:33 +0200 Subject: [PATCH 06/15] Pass booking data from tx page to checkout --- .../BookingPanel/BookingPanel.example.js | 4 +- src/components/BookingPanel/BookingPanel.js | 6 +-- .../TransactionPanel.helpers.js | 2 + .../TransactionPanel/TransactionPanel.js | 3 ++ .../TransactionPanel/TransactionPanel.test.js | 2 + .../TransactionPanel.test.js.snap | 14 ++++++ .../CheckoutPage/CheckoutPage.duck.js | 1 + src/containers/CheckoutPage/CheckoutPage.js | 17 +++++-- .../CheckoutPage/CheckoutPage.test.js | 1 + .../CheckoutPageSessionHelpers.js | 33 +++++++++++-- src/containers/ListingPage/ListingPage.js | 2 +- .../__snapshots__/ListingPage.test.js.snap | 2 +- .../TransactionPage/TransactionPage.js | 48 +++++++++++++++++++ .../TransactionPage/TransactionPage.test.js | 20 ++++++++ .../TransactionPage.test.js.snap | 2 + 15 files changed, 143 insertions(+), 14 deletions(-) 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 87ebd94a98..5a73862d16 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, @@ -116,7 +116,7 @@ const BookingPanel = props => { className={css.bookingForm} submitButtonWrapperClassName={css.bookingDatesSubmitButtonWrapper} unitType={unitType} - onSubmit={handleBookingSubmit} + onSubmit={onSubmit} price={price} isOwnListing={isOwnListing} timeSlots={timeSlots} @@ -167,7 +167,7 @@ BookingPanel.propTypes = { listing: propTypes.listing.isRequired, isOwnListing: bool, unitType: propTypes.bookingUnitType, - handleBookingSubmit: func.isRequired, + onSubmit: func.isRequired, title: oneOfType([node, string]).isRequired, subTitle: oneOfType([node, 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 b5d5b5cb08..304549a889 100644 --- a/src/containers/ListingPage/ListingPage.js +++ b/src/containers/ListingPage/ListingPage.js @@ -442,7 +442,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 e8df2d935c..03d7922570 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} From bbac34a0e57c8d9d255bda6a5c7ca2ec8d13962c Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 17 Dec 2018 23:29:49 +0200 Subject: [PATCH 07/15] Add initiate order after enquiry If enquired transaction is avalable transition it to prequthorized on checkout page. --- .../CheckoutPage/CheckoutPage.duck.js | 39 ++++++++++++++++++- src/containers/CheckoutPage/CheckoutPage.js | 24 ++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.duck.js b/src/containers/CheckoutPage/CheckoutPage.duck.js index 059d1bc159..f6b1bd5c6d 100644 --- a/src/containers/CheckoutPage/CheckoutPage.duck.js +++ b/src/containers/CheckoutPage/CheckoutPage.duck.js @@ -2,7 +2,7 @@ import pick from 'lodash/pick'; import config from '../../config'; import { denormalisedResponseEntities } from '../../util/data'; import { storableError } from '../../util/errors'; -import { TRANSITION_REQUEST } from '../../util/types'; +import { TRANSITION_REQUEST, TRANSITION_REQUEST_AFTER_ENQUIRY } from '../../util/types'; import * as log from '../../util/log'; import { fetchCurrentUserHasOrdersSuccess } from '../../ducks/user.duck'; @@ -146,6 +146,43 @@ export const initiateOrder = (orderParams, initialMessage) => (dispatch, getStat }); }; +/** + * Initiate an order after an enquiry. Transitions previously created transaction. + */ +export const initiateOrderAfterEnquiry = (transactionId, orderParams) => ( + dispatch, + getState, + sdk +) => { + dispatch(initiateOrderRequest()); + + const bodyParams = { + id: transactionId, + transition: TRANSITION_REQUEST_AFTER_ENQUIRY, + params: orderParams, + }; + + return sdk.transactions + .transition(bodyParams) + .then(response => { + const orderId = response.data.data.id; + dispatch(initiateOrderSuccess(orderId)); + dispatch(fetchCurrentUserHasOrdersSuccess(true)); + // set initialMessageSuccess to true to unify promise handling with initiateOrder + return Promise.resolve({ orderId, initialMessageSuccess: true }); + }) + .catch(e => { + dispatch(initiateOrderError(storableError(e))); + log.error(e, 'initiate-order-failed', { + transactionId: transactionId.uuid, + listingId: orderParams.listingId.uuid, + bookingStart: orderParams.bookingStart, + bookingEnd: orderParams.bookingEnd, + }); + throw e; + }); +}; + /** * Initiate the speculative transaction with the given booking details * diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index b2ba4cdfda..b311a5a836 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -30,7 +30,12 @@ import { } from '../../components'; import { StripePaymentForm } from '../../forms'; import { isScrollingDisabled } from '../../ducks/UI.duck'; -import { initiateOrder, setInitialValues, speculateTransaction } from './CheckoutPage.duck'; +import { + initiateOrder, + initiateOrderAfterEnquiry, + setInitialValues, + speculateTransaction, +} from './CheckoutPage.duck'; import config from '../../config'; import { storeData, storedData, clearData } from './CheckoutPageSessionHelpers'; @@ -139,7 +144,14 @@ export class CheckoutPageComponent extends Component { const cardToken = values.token; const initialMessage = values.message; - const { history, sendOrderRequest, speculatedTransaction, dispatch } = this.props; + const { + history, + sendOrderRequest, + sendOrderRequestAfterEnquiry, + speculatedTransaction, + enquiredTransaction, + dispatch, + } = this.props; // Create order aka transaction // NOTE: if unit type is line-item/units, quantity needs to be added. @@ -151,7 +163,11 @@ export class CheckoutPageComponent extends Component { bookingEnd: speculatedTransaction.booking.attributes.end, }; - sendOrderRequest(requestParams, initialMessage) + const initiateRequest = enquiredTransaction + ? sendOrderRequestAfterEnquiry(enquiredTransaction.id, requestParams) + : sendOrderRequest(requestParams, initialMessage); + + initiateRequest .then(values => { const { orderId, initialMessageSuccess } = values; this.setState({ submitting: false }); @@ -538,6 +554,8 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => ({ dispatch, sendOrderRequest: (params, initialMessage) => dispatch(initiateOrder(params, initialMessage)), + sendOrderRequestAfterEnquiry: (transactionId, params) => + dispatch(initiateOrderAfterEnquiry(transactionId, params)), fetchSpeculatedTransaction: params => dispatch(speculateTransaction(params)), }); From 8d2adf01401bde8e3fb56e031b17fcc92c738089 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Mon, 17 Dec 2018 23:55:04 +0200 Subject: [PATCH 08/15] Hide initial message on booking after enquiry --- src/containers/CheckoutPage/CheckoutPage.js | 4 +++ .../__snapshots__/CheckoutPage.test.js.snap | 1 + .../StripePaymentForm/StripePaymentForm.js | 35 ++++++++++++------- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index b311a5a836..79bd753921 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -198,6 +198,7 @@ export class CheckoutPageComponent extends Component { speculateTransactionInProgress, speculateTransactionError, speculatedTransaction, + enquiredTransaction, initiateOrderError, intl, params, @@ -384,6 +385,8 @@ export class CheckoutPageComponent extends Component {
); + const showInitialMessageInput = !enquiredTransaction; + const pageProps = { title, scrollingDisabled }; if (isLoading) { @@ -443,6 +446,7 @@ export class CheckoutPageComponent extends Component { formId="CheckoutPagePaymentForm" paymentInfo={intl.formatMessage({ id: 'CheckoutPage.paymentInfo' })} authorDisplayName={currentAuthor.attributes.profile.displayName} + showInitialMessageInput={showInitialMessageInput} /> ) : null} diff --git a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap index 0e3759cee6..9b19a805db 100644 --- a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap +++ b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap @@ -90,6 +90,7 @@ exports[`CheckoutPage matches snapshot 1`] = ` inProgress={false} onSubmit={[Function]} paymentInfo="CheckoutPage.paymentInfo" + showInitialMessageInput={true} />
diff --git a/src/forms/StripePaymentForm/StripePaymentForm.js b/src/forms/StripePaymentForm/StripePaymentForm.js index d49db25c0c..e8779e0107 100644 --- a/src/forms/StripePaymentForm/StripePaymentForm.js +++ b/src/forms/StripePaymentForm/StripePaymentForm.js @@ -192,6 +192,7 @@ class StripePaymentForm extends Component { paymentInfo, onChange, authorDisplayName, + showInitialMessageInput, intl, } = this.props; const submitInProgress = this.state.submitting || inProgress; @@ -225,6 +226,24 @@ class StripePaymentForm extends Component { ); + const initialMessage = showInitialMessageInput ? ( +
+

+ +

+ + +
+ ) : null; + return (

@@ -243,19 +262,7 @@ class StripePaymentForm extends Component { {this.state.error && !submitInProgress ? ( {this.state.error} ) : null} -

- -

- - + {initialMessage}

{paymentInfo}

null, + showInitialMessageInput: true, }; const { bool, func, string } = PropTypes; @@ -291,6 +299,7 @@ StripePaymentForm.propTypes = { onChange: func, paymentInfo: string.isRequired, authorDisplayName: string.isRequired, + showInitialMessageInput: bool, }; export default injectIntl(StripePaymentForm); From 4663f825a161f7eaee13e0ec058cbadb82ffb59a Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 09:54:30 +0200 Subject: [PATCH 09/15] Change checkout page booking sub title Unify the sub title with transaction page. --- src/containers/CheckoutPage/CheckoutPage.css | 5 ++-- src/containers/CheckoutPage/CheckoutPage.js | 26 ++++++++++++++----- .../__snapshots__/CheckoutPage.test.js.snap | 9 +------ src/translations/en.json | 3 +++ src/translations/fr.json | 5 +++- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.css b/src/containers/CheckoutPage/CheckoutPage.css index acd516f38a..efab0ca5a8 100644 --- a/src/containers/CheckoutPage/CheckoutPage.css +++ b/src/containers/CheckoutPage/CheckoutPage.css @@ -310,13 +310,12 @@ @media (--viewportLarge) { margin-top: 17px; - margin-bottom: 0; + margin-bottom: 9px; } } .detailsSubtitle { @apply --marketplaceH5FontStyles; - color: var(--matterColorAnti); /* Reset margins from font styles */ margin-top: 0; @@ -336,7 +335,7 @@ margin: 5px 24px 25px 24px; @media (--viewportLarge) { - margin: 38px 48px 26px 48px; + margin: 37px 48px 26px 48px; } } diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index 79bd753921..fb3fabb5f2 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -7,7 +7,7 @@ import { withRouter } from 'react-router-dom'; import classNames from 'classnames'; import routeConfiguration from '../../routeConfiguration'; import { pathByRouteName, findRouteByRouteName } from '../../util/routes'; -import { propTypes } from '../../util/types'; +import { propTypes, LINE_ITEM_NIGHT, LINE_ITEM_DAY } from '../../util/types'; import { ensureListing, ensureUser, ensureTransaction, ensureBooking } from '../../util/data'; import { dateFromLocalToAPI } from '../../util/dates'; import { createSlug } from '../../util/urlHelpers'; @@ -19,6 +19,7 @@ import { isTransactionZeroPaymentError, transactionInitiateOrderStripeErrors, } from '../../util/errors'; +import { formatMoney } from '../../util/currency'; import { AvatarMedium, BookingBreakdown, @@ -163,6 +164,8 @@ export class CheckoutPageComponent extends Component { bookingEnd: speculatedTransaction.booking.attributes.end, }; + // if an enquired transactioni is available, use that as basis + // otherwise initiate a new transaction const initiateRequest = enquiredTransaction ? sendOrderRequestAfterEnquiry(enquiredTransaction.id, requestParams) : sendOrderRequest(requestParams, initialMessage); @@ -385,6 +388,20 @@ export class CheckoutPageComponent extends Component {
); + const unitType = config.bookingUnitType; + const isNightly = unitType === LINE_ITEM_NIGHT; + const isDaily = unitType === LINE_ITEM_DAY; + + const unitTranslationKey = isNightly + ? 'CheckoutPage.perNight' + : isDaily + ? 'CheckoutPage.perDay' + : 'CheckoutPage.perUnit'; + + const price = currentListing.attributes.price; + const formattedPrice = formatMoney(intl, price); + const detailsSubTitle = `${formattedPrice} ${intl.formatMessage({ id: unitTranslationKey })}`; + const showInitialMessageInput = !enquiredTransaction; const pageProps = { title, scrollingDisabled }; @@ -466,12 +483,7 @@ export class CheckoutPageComponent extends Component {

{listingTitle}

-

- -

+

{detailsSubTitle}

diff --git a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap index 9b19a805db..0002043f12 100644 --- a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap +++ b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap @@ -135,14 +135,7 @@ exports[`CheckoutPage matches snapshot 1`] = ` listing1 title

- + 55 CheckoutPage.perNight

diff --git a/src/translations/en.json b/src/translations/en.json index ac9a21e577..a18827bad5 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -84,6 +84,9 @@ "CheckoutPage.listingNotFoundError": "Unfortunately, the listing is no longer available.", "CheckoutPage.loadingData": "Loading checkout data…", "CheckoutPage.paymentInfo": "You'll only be charged if your request is accepted by the provider.", + "CheckoutPage.perDay": "per day", + "CheckoutPage.perNight": "per night", + "CheckoutPage.perUnit": "per unit", "CheckoutPage.priceBreakdownTitle": "Booking breakdown", "CheckoutPage.providerStripeAccountMissingError": "The listing author has not added their payment information and the listing cannot be booked at the moment.", "CheckoutPage.speculateFailedMessage": "Oops, something went wrong. Please refresh the page and try again.", diff --git a/src/translations/fr.json b/src/translations/fr.json index 18fb37ec2b..b97c7fffc9 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -84,6 +84,9 @@ "CheckoutPage.listingNotFoundError": "Hélas, cette annonce n'est plus disponible.", "CheckoutPage.loadingData": "Chargement des données de paiement…", "CheckoutPage.paymentInfo": "Vous ne serez facturé que si votre demande est acceptée par l'hôte.", + "CheckoutPage.perDay": "par jour", + "CheckoutPage.perNight": "par nuit", + "CheckoutPage.perUnit": "per unit", "CheckoutPage.priceBreakdownTitle": "Détails de la réservation", "CheckoutPage.providerStripeAccountMissingError": "L'auteur de l'annonce n'a pas ajouté ses coordonnées bancaires et l'annonce ne peut pas être réserver pour le moment.", "CheckoutPage.speculateFailedMessage": "Oups, quelque chose n'a pas fonctionné. Veuillez rafraichir la page et essayer de nouveau.", @@ -786,7 +789,7 @@ "TransactionPanel.orderPreauthorizedInfo": "{providerName} a reçu un message à propos de votre demande de réservation.", "TransactionPanel.orderPreauthorizedSubtitle": "Vous avez fait une demande de réservation {listingLink}.", "TransactionPanel.orderPreauthorizedTitle": "Bravo, {customerName} !", - "TransactionPanel.perDay": "per day", + "TransactionPanel.perDay": "par jour", "TransactionPanel.perNight": "par nuit", "TransactionPanel.perUnit": "per unit", "TransactionPanel.requestToBook": "Réserver", From 65a1358b93a5bf9a12e9e9dec72f84794bf6df34 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 10:26:07 +0200 Subject: [PATCH 10/15] Fix hidden open booking form section in mobile --- .../TransactionPanel/TransactionPanel.css | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index e1e8c44bb2..9ab5387db1 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -73,9 +73,11 @@ } .avatarWrapperCustomerDesktop { + display: none; composes: avatarWrapperMobile; @media (--viewportLarge) { + display: block; margin-left: 48px; } } @@ -171,25 +173,26 @@ } .detailCard { - display: none; - - position: sticky; - top: -200px; /* This is a hack to showcase how the component would look when the image isn't sticky */ - width: 409px; - background-color: var(--matterColorLight); - border: 1px solid var(--matterColorNegative); - border-radius: 2px; - @media (--viewportLarge) { - display: block; + position: sticky; + top: -200px; /* This is a hack to showcase how the component would look when the image isn't sticky */ + width: 409px; + background-color: var(--matterColorLight); + border: 1px solid var(--matterColorNegative); + border-radius: 2px; } } .detailCardImageWrapper { + display: none; + /* Layout */ - display: block; width: 100%; position: relative; + + @media (--viewportLarge) { + display: block; + } } .detailCardHeadings { From 08378d700134b2b36d038a01a5afb1d9dd84fc39 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 10:31:53 +0200 Subject: [PATCH 11/15] Fix footer overlapping booking calendar Rise the transaction details section on top of the footer so that the booking dates calendar won't go below it. --- src/components/TransactionPanel/TransactionPanel.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index 9ab5387db1..f4f31e4291 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -180,6 +180,7 @@ background-color: var(--matterColorLight); border: 1px solid var(--matterColorNegative); border-radius: 2px; + z-index: 1; } } From 29875d421003bbbacb487eff5261f827612daa3c Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 10:55:51 +0200 Subject: [PATCH 12/15] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f03d7a792c..7171c19d67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ way to update this template, but currently, we follow a pattern: [#985](https://github.com/sharetribe/flex-template-web/pull/985) - [remove] Remove the default built-in email templates. Built-in email templates can be edited in Console. [#983](https://github.com/sharetribe/flex-template-web/pull/983) +- [add] Enable booking a listing straight from an enquiry + [#976](https://github.com/sharetribe/flex-template-web/pull/976) - [change] Extract SectionBooking to a distinct component from ListingPage. [#969](https://github.com/sharetribe/flex-template-web/pull/969) From 4f21f3a214f419541b597eff80994f769706b731 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 11:36:41 +0200 Subject: [PATCH 13/15] Hide desktop booking breakdown in mobile --- src/components/TransactionPanel/TransactionPanel.css | 8 ++++++++ .../TransactionPanel/TransactionPanel.helpers.js | 10 ++++++---- src/components/TransactionPanel/TransactionPanel.js | 6 +++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.css b/src/components/TransactionPanel/TransactionPanel.css index f4f31e4291..b95b2ec88b 100644 --- a/src/components/TransactionPanel/TransactionPanel.css +++ b/src/components/TransactionPanel/TransactionPanel.css @@ -249,6 +249,14 @@ } } +.breakdownContainer { + display: none; + + @media (--viewportLarge) { + display: block; + } +} + .breakdown { margin: 14px 24px 0 24px; diff --git a/src/components/TransactionPanel/TransactionPanel.helpers.js b/src/components/TransactionPanel/TransactionPanel.helpers.js index 691bdacca9..3c0acc3f44 100644 --- a/src/components/TransactionPanel/TransactionPanel.helpers.js +++ b/src/components/TransactionPanel/TransactionPanel.helpers.js @@ -115,17 +115,19 @@ export const AddressLinkMaybe = props => { // Functional component as a helper to build BookingBreakdown export const BreakdownMaybe = props => { - const { className, rootClassName, transaction, transactionRole } = props; + const { className, rootClassName, breakdownClassName, transaction, transactionRole } = props; const loaded = transaction && transaction.id && transaction.booking && transaction.booking.id; - const classes = classNames(rootClassName || css.breakdown, className); + const classes = classNames(rootClassName || className); + const breakdownClasses = classNames(css.breakdown, breakdownClassName); + return loaded ? ( -
+

- + {canShowActionButtons ? (
{actionButtons}
From ad6fc6346bc3e849a7a4341f49a75eba317b1e8a Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 12:09:38 +0200 Subject: [PATCH 14/15] Fix session store handling for enquired tx --- src/containers/CheckoutPage/CheckoutPage.js | 8 ++++---- src/containers/CheckoutPage/CheckoutPageSessionHelpers.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js index fb3fabb5f2..030f949c3c 100644 --- a/src/containers/CheckoutPage/CheckoutPage.js +++ b/src/containers/CheckoutPage/CheckoutPage.js @@ -150,7 +150,6 @@ export class CheckoutPageComponent extends Component { sendOrderRequest, sendOrderRequestAfterEnquiry, speculatedTransaction, - enquiredTransaction, dispatch, } = this.props; @@ -164,7 +163,9 @@ export class CheckoutPageComponent extends Component { bookingEnd: speculatedTransaction.booking.attributes.end, }; - // if an enquired transactioni is available, use that as basis + const enquiredTransaction = this.state.pageData.enquiredTransaction; + + // if an enquired transaction is available, use that as basis // otherwise initiate a new transaction const initiateRequest = enquiredTransaction ? sendOrderRequestAfterEnquiry(enquiredTransaction.id, requestParams) @@ -201,7 +202,6 @@ export class CheckoutPageComponent extends Component { speculateTransactionInProgress, speculateTransactionError, speculatedTransaction, - enquiredTransaction, initiateOrderError, intl, params, @@ -220,7 +220,7 @@ export class CheckoutPageComponent extends Component { const isLoading = !this.state.dataLoaded || speculateTransactionInProgress; - const { listing, bookingDates } = this.state.pageData; + const { listing, bookingDates, enquiredTransaction } = this.state.pageData; const currentTransaction = ensureTransaction(speculatedTransaction, {}, null); const currentBooking = ensureBooking(currentTransaction.booking); const currentListing = ensureListing(listing); diff --git a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js index f45c826999..b74910087d 100644 --- a/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js +++ b/src/containers/CheckoutPage/CheckoutPageSessionHelpers.js @@ -53,7 +53,7 @@ export const isValidEnquiredTransaction = transaction => { const props = { id: id => id instanceof UUID, attributes: v => { - return typeof v === 'string' && v.lastTransition === TRANSITION_ENQUIRE; + return typeof v === 'object' && v.lastTransition === TRANSITION_ENQUIRE; }, }; return validateProperties(transaction, props); From 1dba15331a5589b6406ec989701b9cd9e203c9f4 Mon Sep 17 00:00:00 2001 From: Hannu Lyytikainen Date: Tue, 18 Dec 2018 12:31:17 +0200 Subject: [PATCH 15/15] Streamline sale buttons visibility logic --- .../TransactionPanel/TransactionPanel.js | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/components/TransactionPanel/TransactionPanel.js b/src/components/TransactionPanel/TransactionPanel.js index 1340a95fba..79d308dd62 100644 --- a/src/components/TransactionPanel/TransactionPanel.js +++ b/src/components/TransactionPanel/TransactionPanel.js @@ -185,24 +185,20 @@ export class TransactionPanelComponent extends Component { currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null; const actionButtonClasses = classNames(css.actionButtons); - const canShowActionButtons = canShowSaleButtons; - - let actionButtons = null; - if (canShowSaleButtons) { - actionButtons = ( - - ); - } + + const saleButtons = ( + + ); const sendMessagePlaceholder = intl.formatMessage( { id: 'TransactionPanel.sendMessagePlaceholder' }, @@ -293,8 +289,8 @@ export class TransactionPanelComponent extends Component { onBlur={this.onSendMessageFormBlur} onSubmit={this.onMessageSubmit} /> - {canShowActionButtons ? ( -
{actionButtons}
+ {canShowSaleButtons ? ( +
{saleButtons}
) : null}
@@ -342,8 +338,8 @@ export class TransactionPanelComponent extends Component { transactionRole={transactionRole} /> - {canShowActionButtons ? ( -
{actionButtons}
+ {canShowSaleButtons ? ( +
{saleButtons}
) : null}