mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 03:43:28 +10:00
Merge pull request #548 from sharetribe/render-order-sale-messages
Order page messages
This commit is contained in:
commit
45d4c82942
10 changed files with 493 additions and 459 deletions
|
|
@ -24,6 +24,7 @@
|
|||
.ownMessage {
|
||||
/* Preserve newlines, but collapse other whitespace */
|
||||
white-space: pre-line;
|
||||
width: 100%;
|
||||
max-width: 433px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,18 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: var(--failColor);
|
||||
margin: 13px 0 22px 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 13px 0 23px 0;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
margin: 12px 0 23px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -72,13 +84,13 @@
|
|||
|
||||
.orderInfo {
|
||||
@media (--viewportLarge) {
|
||||
max-width: 519px;
|
||||
margin-right: 132px;
|
||||
max-width: 538px;
|
||||
margin-right: 108px;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin: 28px 24px 0 24px;
|
||||
margin: 27px 24px 0 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
max-width: 80%;
|
||||
|
|
@ -94,18 +106,27 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.messagesContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.orderInfoText {
|
||||
margin: 18px 24px 0 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 23px 24px 0 24px;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
margin: 23px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
margin: 24px 24px 47px 24px;
|
||||
.infoTextDivider {
|
||||
display: none;
|
||||
|
||||
height: 1px;
|
||||
background-color: var(--matterColorNegative);
|
||||
border: none;
|
||||
margin: 37px 0 0 0;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin: 31px 0 0 0;
|
||||
line-height: 32px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +135,11 @@
|
|||
}
|
||||
|
||||
.breakdownMobile {
|
||||
margin-top: 47px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-top: 43px;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -176,7 +202,7 @@
|
|||
margin-bottom: 0;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin-top: 0;
|
||||
margin-top: 1px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -185,25 +211,54 @@
|
|||
/* Font */
|
||||
color: var(--matterColorAnti);
|
||||
|
||||
margin-top: 5px;
|
||||
margin-bottom: 14px;
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
margin: 0 24px 0 24px;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin-top: 38px;
|
||||
margin-bottom: 25px;
|
||||
margin-left: 48px;
|
||||
margin-right: 48px;
|
||||
margin: 37px 48px 26px 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.receipt {
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
.breakdown {
|
||||
margin: 14px 24px 0 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 18px 24px 0 24px;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
margin-left: 48px;
|
||||
margin-right: 48px;
|
||||
margin: 14px 48px 0 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.messagesContainer {
|
||||
margin: 46px 24px 0 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 46px 24px 0 24px;
|
||||
}
|
||||
@media (--viewportLarge) {
|
||||
margin: 43px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messagesContainerWithInfoAbove {
|
||||
@media (--viewportLarge) {
|
||||
margin: 38px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messagesHeading {
|
||||
color: var(--matterColorAnti);
|
||||
margin: 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messages {
|
||||
margin-top: 17px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-top: 19px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl, intlShape, FormattedDate, FormattedMessage } from 'react-intl';
|
||||
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { createSlug } from '../../util/urlHelpers';
|
||||
import { ensureListing, ensureTransaction, ensureUser, userDisplayName } from '../../util/data';
|
||||
import { BookingBreakdown, NamedLink, ResponsiveImage, AvatarMedium } from '../../components';
|
||||
import {
|
||||
BookingBreakdown,
|
||||
NamedLink,
|
||||
ResponsiveImage,
|
||||
AvatarMedium,
|
||||
Messages,
|
||||
} from '../../components';
|
||||
|
||||
import css from './OrderDetailsPanel.css';
|
||||
|
||||
|
|
@ -14,7 +20,7 @@ const breakdown = transaction => {
|
|||
|
||||
return loaded ? (
|
||||
<BookingBreakdown
|
||||
className={css.receipt}
|
||||
className={css.breakdown}
|
||||
userRole="customer"
|
||||
transaction={transaction}
|
||||
booking={transaction.booking}
|
||||
|
|
@ -62,60 +68,26 @@ const orderTitle = (transaction, listingLink, customerName) => {
|
|||
}
|
||||
};
|
||||
|
||||
const orderMessage = (transaction, listingTitle, providerName) => {
|
||||
const transitionDate = (
|
||||
<span className={css.transitionDate}>
|
||||
<FormattedDate
|
||||
value={transaction.attributes.lastTransitionedAt}
|
||||
year="numeric"
|
||||
month="short"
|
||||
day="numeric"
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
const orderMessage = (transaction, providerName) => {
|
||||
if (propTypes.txIsPreauthorized(transaction)) {
|
||||
return (
|
||||
<FormattedMessage id="OrderDetailsPanel.orderPreauthorizedStatus" values={{ providerName }} />
|
||||
);
|
||||
} else if (propTypes.txIsAccepted(transaction)) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAcceptedStatus"
|
||||
values={{ providerName, transitionDate }}
|
||||
/>
|
||||
);
|
||||
} else if (propTypes.txIsDeclined(transaction)) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeclinedStatus"
|
||||
values={{ providerName, transitionDate }}
|
||||
/>
|
||||
);
|
||||
} else if (propTypes.txIsAutodeclined(transaction)) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAutoDeclinedStatus"
|
||||
values={{ providerName, transitionDate }}
|
||||
/>
|
||||
);
|
||||
} else if (propTypes.txIsCanceled(transaction)) {
|
||||
return (
|
||||
<FormattedMessage id="OrderDetailsPanel.orderCanceledStatus" values={{ transitionDate }} />
|
||||
);
|
||||
} else if (propTypes.txIsDelivered(transaction)) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeliveredStatus"
|
||||
values={{ providerName, transitionDate }}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const OrderDetailsPanelComponent = props => {
|
||||
const { rootClassName, className, transaction, intl } = props;
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
currentUser,
|
||||
transaction,
|
||||
messages,
|
||||
initialMessageFailed,
|
||||
fetchMessagesError,
|
||||
intl,
|
||||
} = props;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const currentProvider = ensureUser(currentTransaction.provider);
|
||||
|
|
@ -160,46 +132,72 @@ export const OrderDetailsPanelComponent = props => {
|
|||
|
||||
const bookingInfo = breakdown(currentTransaction);
|
||||
const orderHeading = orderTitle(currentTransaction, listingLink, customerDisplayName);
|
||||
const message = listingDeleted
|
||||
const orderInfoText = listingDeleted
|
||||
? orderMessageDeletedListing
|
||||
: orderMessage(currentTransaction, listingLink, authorDisplayName);
|
||||
: orderMessage(currentTransaction, authorDisplayName);
|
||||
const showInfoMessage = !!orderInfoText;
|
||||
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
|
||||
const messagesContainerClasses = classNames(css.messagesContainer, {
|
||||
[css.messagesContainerWithInfoAbove]: showInfoMessage,
|
||||
});
|
||||
const showMessages = messages.length > 0 || initialMessageFailed || fetchMessagesError;
|
||||
const messagesContainer = showMessages ? (
|
||||
<div className={messagesContainerClasses}>
|
||||
<h3 className={css.messagesHeading}>
|
||||
<FormattedMessage id="OrderDetailsPanel.messagesHeading" />
|
||||
</h3>
|
||||
{initialMessageFailed ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="OrderDetailsPanel.initialMessageFailed" />
|
||||
</p>
|
||||
) : null}
|
||||
{fetchMessagesError ? (
|
||||
<p className={css.error}>
|
||||
<FormattedMessage id="OrderDetailsPanel.messageLoadingFailed" />
|
||||
</p>
|
||||
) : null}
|
||||
<Messages className={css.messages} messages={messages} currentUser={currentUser} />
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={css.container}>
|
||||
<div className={css.imageWrapperMobile}>
|
||||
<div className={css.aspectWrapper}>
|
||||
<ResponsiveImage
|
||||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classNames(css.avatarWrapper, css.avatarMobile)}>
|
||||
<AvatarMedium user={currentProvider} />
|
||||
</div>
|
||||
<div className={css.orderInfo}>
|
||||
<div className={css.imageWrapperMobile}>
|
||||
<div className={css.aspectWrapper}>
|
||||
<ResponsiveImage
|
||||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classNames(css.avatarWrapper, css.avatarMobile)}>
|
||||
<AvatarMedium user={currentProvider} />
|
||||
</div>
|
||||
<h1 className={css.heading}>{orderHeading}</h1>
|
||||
<div className={css.message}>{message}</div>
|
||||
</div>
|
||||
<div className={css.bookingBreakdownContainer}>
|
||||
{showInfoMessage ? <p className={css.orderInfoText}>{orderInfoText}</p> : null}
|
||||
{showInfoMessage ? <hr className={css.infoTextDivider} /> : null}
|
||||
<div className={css.breakdownMobile}>
|
||||
<h3 className={css.bookingBreakdownTitle}>
|
||||
<FormattedMessage id="OrderDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
{messagesContainer}
|
||||
</div>
|
||||
<div className={css.bookingBreakdownContainer}>
|
||||
<div className={css.breakdownDesktop}>
|
||||
<div className={css.breakdownImageWrapper}>
|
||||
<div className={css.aspectWrapper}>
|
||||
|
|
@ -241,14 +239,20 @@ export const OrderDetailsPanelComponent = props => {
|
|||
OrderDetailsPanelComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
fetchMessagesError: null,
|
||||
};
|
||||
|
||||
const { string } = PropTypes;
|
||||
const { string, arrayOf, bool } = PropTypes;
|
||||
|
||||
OrderDetailsPanelComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
className: string,
|
||||
|
||||
currentUser: propTypes.currentUser,
|
||||
transaction: propTypes.transaction.isRequired,
|
||||
messages: arrayOf(propTypes.message).isRequired,
|
||||
initialMessageFailed: bool.isRequired,
|
||||
fetchMessagesError: propTypes.error,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape,
|
||||
|
|
|
|||
|
|
@ -58,39 +58,45 @@ const txDelivered = createTransaction({
|
|||
});
|
||||
|
||||
describe('OrderDetailsPanel', () => {
|
||||
const panelBaseProps = {
|
||||
intl: fakeIntl,
|
||||
messages: [],
|
||||
initialMessageFailed: false,
|
||||
};
|
||||
|
||||
it('preauthorized matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txPreauthorized} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txPreauthorized} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
it('accepted matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txAccepted} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txAccepted} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
it('declined matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txDeclined} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txDeclined} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
it('autodeclined matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txAutoDeclined} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txAutoDeclined} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
it('canceled matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txCanceled} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txCanceled} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
it('delivered matches snapshot', () => {
|
||||
const tree = renderShallow(
|
||||
<OrderDetailsPanelComponent transaction={txDelivered} intl={fakeIntl} />
|
||||
<OrderDetailsPanelComponent transaction={txDelivered} {...panelBaseProps} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
|
@ -108,7 +114,7 @@ describe('OrderDetailsPanel', () => {
|
|||
provider: createUser('provider'),
|
||||
customer: createUser('customer'),
|
||||
});
|
||||
const panel = shallow(<OrderDetailsPanelComponent transaction={tx} intl={fakeIntl} />);
|
||||
const panel = shallow(<OrderDetailsPanelComponent transaction={tx} {...panelBaseProps} />);
|
||||
const breakdownProps = panel.find(BookingBreakdown).props();
|
||||
expect(breakdownProps.transaction.attributes.payinTotal).toEqual(new Money(16500, 'USD'));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,50 +7,50 @@ exports[`OrderDetailsPanel accepted matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<span>
|
||||
<span>
|
||||
|
|
@ -83,26 +83,6 @@ exports[`OrderDetailsPanel accepted matches snapshot 1`] = `
|
|||
/>
|
||||
</span>
|
||||
</h1>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAcceptedStatus"
|
||||
values={
|
||||
Object {
|
||||
"providerName": "provider display name",
|
||||
"transitionDate": <span>
|
||||
<FormattedDate
|
||||
day="numeric"
|
||||
month="short"
|
||||
value={2017-06-01T00:00:00.000Z}
|
||||
year="numeric"
|
||||
/>
|
||||
</span>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -231,6 +211,8 @@ exports[`OrderDetailsPanel accepted matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -429,50 +411,50 @@ exports[`OrderDetailsPanel autodeclined matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAutoDeclinedTitle"
|
||||
|
|
@ -493,26 +475,6 @@ exports[`OrderDetailsPanel autodeclined matches snapshot 1`] = `
|
|||
}
|
||||
/>
|
||||
</h1>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAutoDeclinedStatus"
|
||||
values={
|
||||
Object {
|
||||
"providerName": "provider display name",
|
||||
"transitionDate": <span>
|
||||
<FormattedDate
|
||||
day="numeric"
|
||||
month="short"
|
||||
value={2017-06-01T00:00:00.000Z}
|
||||
year="numeric"
|
||||
/>
|
||||
</span>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -641,6 +603,8 @@ exports[`OrderDetailsPanel autodeclined matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -839,50 +803,50 @@ exports[`OrderDetailsPanel canceled matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<span>
|
||||
<span>
|
||||
|
|
@ -915,7 +879,7 @@ exports[`OrderDetailsPanel canceled matches snapshot 1`] = `
|
|||
/>
|
||||
</span>
|
||||
</h1>
|
||||
<div>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderPreauthorizedStatus"
|
||||
values={
|
||||
|
|
@ -924,9 +888,8 @@ exports[`OrderDetailsPanel canceled matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</p>
|
||||
<hr />
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -1055,6 +1018,8 @@ exports[`OrderDetailsPanel canceled matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -1253,50 +1218,50 @@ exports[`OrderDetailsPanel declined matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeclinedTitle"
|
||||
|
|
@ -1317,26 +1282,6 @@ exports[`OrderDetailsPanel declined matches snapshot 1`] = `
|
|||
}
|
||||
/>
|
||||
</h1>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeclinedStatus"
|
||||
values={
|
||||
Object {
|
||||
"providerName": "provider display name",
|
||||
"transitionDate": <span>
|
||||
<FormattedDate
|
||||
day="numeric"
|
||||
month="short"
|
||||
value={2017-06-01T00:00:00.000Z}
|
||||
year="numeric"
|
||||
/>
|
||||
</span>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -1465,6 +1410,8 @@ exports[`OrderDetailsPanel declined matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -1663,50 +1610,50 @@ exports[`OrderDetailsPanel delivered matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeliveredTitle"
|
||||
|
|
@ -1727,26 +1674,6 @@ exports[`OrderDetailsPanel delivered matches snapshot 1`] = `
|
|||
}
|
||||
/>
|
||||
</h1>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderDeliveredStatus"
|
||||
values={
|
||||
Object {
|
||||
"providerName": "provider display name",
|
||||
"transitionDate": <span>
|
||||
<FormattedDate
|
||||
day="numeric"
|
||||
month="short"
|
||||
value={2017-06-01T00:00:00.000Z}
|
||||
year="numeric"
|
||||
/>
|
||||
</span>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -1875,6 +1802,8 @@ exports[`OrderDetailsPanel delivered matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -2073,50 +2002,50 @@ exports[`OrderDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
<div>
|
||||
<ResponsiveImage
|
||||
alt="listing1 title"
|
||||
className={null}
|
||||
image={null}
|
||||
nameSet={
|
||||
Array [
|
||||
Object {
|
||||
"name": "landscape-crop",
|
||||
"size": "400w",
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
},
|
||||
]
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"name": "landscape-crop2x",
|
||||
"size": "800w",
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
]
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
noImageMessage={null}
|
||||
rootClassName={null}
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<AvatarMedium
|
||||
user={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "TT",
|
||||
"displayName": "provider display name",
|
||||
},
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider",
|
||||
},
|
||||
"type": "user",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<h1>
|
||||
<span>
|
||||
<span>
|
||||
|
|
@ -2149,7 +2078,7 @@ exports[`OrderDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
/>
|
||||
</span>
|
||||
</h1>
|
||||
<div>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderPreauthorizedStatus"
|
||||
values={
|
||||
|
|
@ -2158,9 +2087,8 @@ exports[`OrderDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</p>
|
||||
<hr />
|
||||
<div>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -2289,6 +2217,8 @@ exports[`OrderDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
userRole="customer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -118,12 +118,15 @@ export const fetchMessages = txId => (dispatch, getState, sdk) => {
|
|||
dispatch(fetchMessagesRequest());
|
||||
|
||||
return sdk.messages
|
||||
.query({ transaction_id: txId })
|
||||
.query({ transaction_id: txId, include: ['sender', 'sender.profileImage'] })
|
||||
.then(response => {
|
||||
const entities = updatedEntities({}, response.data);
|
||||
const messageIds = response.data.data.map(d => d.id);
|
||||
const denormalized = denormalisedEntities(entities, 'message', messageIds);
|
||||
|
||||
// Messages come latest first, so we need to reverse the order
|
||||
denormalized.reverse();
|
||||
|
||||
dispatch(fetchMessagesSuccess(denormalized));
|
||||
})
|
||||
.catch(e => {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ export const OrderPageComponent = props => {
|
|||
const {
|
||||
currentUser,
|
||||
fetchOrderError,
|
||||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
intl,
|
||||
params,
|
||||
|
|
@ -39,13 +41,11 @@ export const OrderPageComponent = props => {
|
|||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const listingTitle = currentListing.attributes.title;
|
||||
|
||||
if (messageSendingFailedToTransaction) {
|
||||
// TODO: render error message with other messages
|
||||
console.error(
|
||||
'failed to send initial message to transaction:',
|
||||
messageSendingFailedToTransaction
|
||||
);
|
||||
}
|
||||
const initialMessageFailed = !!(
|
||||
messageSendingFailedToTransaction &&
|
||||
currentTransaction.id &&
|
||||
messageSendingFailedToTransaction.uuid === currentTransaction.id.uuid
|
||||
);
|
||||
|
||||
// Redirect users with someone else's direct link to their own inbox/orders page.
|
||||
const isDataAvailable =
|
||||
|
|
@ -77,7 +77,14 @@ export const OrderPageComponent = props => {
|
|||
|
||||
const panel =
|
||||
isDataAvailable && currentTransaction.id ? (
|
||||
<OrderDetailsPanel className={detailsClassName} transaction={currentTransaction} />
|
||||
<OrderDetailsPanel
|
||||
className={detailsClassName}
|
||||
currentUser={currentUser}
|
||||
transaction={currentTransaction}
|
||||
messages={messages}
|
||||
initialMessageFailed={initialMessageFailed}
|
||||
fetchMessagesError={fetchMessagesError}
|
||||
/>
|
||||
) : (
|
||||
loadingOrFaildFetching
|
||||
);
|
||||
|
|
@ -103,31 +110,46 @@ export const OrderPageComponent = props => {
|
|||
OrderPageComponent.defaultProps = {
|
||||
currentUser: null,
|
||||
fetchOrderError: null,
|
||||
fetchMessagesError: null,
|
||||
messageSendingFailedToTransaction: null,
|
||||
transaction: null,
|
||||
};
|
||||
|
||||
const { bool, oneOf, shape, string } = PropTypes;
|
||||
const { bool, oneOf, shape, string, array } = PropTypes;
|
||||
|
||||
OrderPageComponent.propTypes = {
|
||||
params: shape({ id: string }).isRequired,
|
||||
tab: oneOf(['details', 'discussion']).isRequired,
|
||||
|
||||
currentUser: propTypes.currentUser,
|
||||
fetchOrderError: propTypes.error,
|
||||
fetchMessagesError: propTypes.error,
|
||||
messages: array.isRequired,
|
||||
messageSendingFailedToTransaction: propTypes.uuid,
|
||||
intl: intlShape.isRequired,
|
||||
params: shape({ id: string }).isRequired,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
tab: oneOf(['details', 'discussion']).isRequired,
|
||||
transaction: propTypes.transaction,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const { fetchOrderError, transactionRef, messageSendingFailedToTransaction } = state.OrderPage;
|
||||
const { currentUser } = state.user;
|
||||
const {
|
||||
fetchOrderError,
|
||||
transactionRef,
|
||||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
} = state.OrderPage;
|
||||
const transactions = getMarketplaceEntities(state, transactionRef ? [transactionRef] : []);
|
||||
const transaction = transactions.length > 0 ? transactions[0] : null;
|
||||
|
||||
return {
|
||||
currentUser,
|
||||
fetchOrderError,
|
||||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
scrollingDisabled: isScrollingDisabled(state),
|
||||
transaction,
|
||||
|
|
|
|||
|
|
@ -29,23 +29,15 @@ describe('OrderPage', () => {
|
|||
});
|
||||
|
||||
const props = {
|
||||
authInProgress: false,
|
||||
currentUserHasListings: false,
|
||||
isAuthenticated: false,
|
||||
onLogout: noop,
|
||||
onManageDisableScrolling: noop,
|
||||
currentUser: createCurrentUser('customer1'),
|
||||
params: { id: txId },
|
||||
transaction,
|
||||
tab: 'details',
|
||||
intl: fakeIntl,
|
||||
|
||||
currentUser: createCurrentUser('customer1'),
|
||||
messages: [],
|
||||
scrollingDisabled: false,
|
||||
location: { search: '' },
|
||||
history: {
|
||||
push: () => console.log('HistoryPush called'),
|
||||
},
|
||||
sendVerificationEmailInProgress: false,
|
||||
onResendVerificationEmail: noop,
|
||||
transaction,
|
||||
|
||||
intl: fakeIntl,
|
||||
};
|
||||
|
||||
const tree = renderShallow(<OrderPageComponent {...props} />);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,29 @@ exports[`OrderPage matches snapshot 1`] = `
|
|||
>
|
||||
<InjectIntl(Component)
|
||||
className="undefined"
|
||||
currentUser={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"email": "customer1@example.com",
|
||||
"emailVerified": true,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "customer1 abbreviated name",
|
||||
"displayName": "customer1 display name",
|
||||
"firstName": "customer1 first name",
|
||||
"lastName": "customer1 last name",
|
||||
},
|
||||
"stripeConnected": true,
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "customer1",
|
||||
},
|
||||
"type": "currentUser",
|
||||
}
|
||||
}
|
||||
fetchMessagesError={null}
|
||||
initialMessageFailed={false}
|
||||
messages={Array []}
|
||||
transaction={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -259,17 +259,15 @@
|
|||
"OrderDetailsPanel.deletedListingOrderTitle": "a listing",
|
||||
"OrderDetailsPanel.deletedListingTitle": "Deleted listing",
|
||||
"OrderDetailsPanel.hostedBy": "Hosted by {name}",
|
||||
"OrderDetailsPanel.initialMessageFailed": "Whoops, failed to send message from checkout.",
|
||||
"OrderDetailsPanel.messageDeletedListing": "However, the listing is deleted and cannot be viewed anymore.",
|
||||
"OrderDetailsPanel.orderAcceptedStatus": "{providerName} accepted the request on {transitionDate}.",
|
||||
"OrderDetailsPanel.messageLoadingFailed": "Something went wrong when loading messages. Please refresh the page and try again.",
|
||||
"OrderDetailsPanel.messagesHeading": "Activity",
|
||||
"OrderDetailsPanel.orderAcceptedSubtitle": "You have booked {listingLink}",
|
||||
"OrderDetailsPanel.orderAcceptedTitle": "Woohoo {customerName}!",
|
||||
"OrderDetailsPanel.orderAutoDeclinedStatus": "The request expired on {transitionDate}. {providerName} never replied to the request.",
|
||||
"OrderDetailsPanel.orderAutoDeclinedTitle": "You requested to book {listingLink}",
|
||||
"OrderDetailsPanel.orderCanceledStatus": "The request was cancelled on {transitionDate}",
|
||||
"OrderDetailsPanel.orderCanceledTitle": "You booked {listingLink}",
|
||||
"OrderDetailsPanel.orderDeclinedStatus": "Unfortunately {providerName} declined the request on {transitionDate}.",
|
||||
"OrderDetailsPanel.orderDeclinedTitle": "You requested to book {listingLink}",
|
||||
"OrderDetailsPanel.orderDeliveredStatus": " ",
|
||||
"OrderDetailsPanel.orderDeliveredTitle": "Booking period has ended",
|
||||
"OrderDetailsPanel.orderPreauthorizedStatus": "{providerName} has been notified about the booking request, so sit back and relax.",
|
||||
"OrderDetailsPanel.orderPreauthorizedSubtitle": "You have requested to book {listingLink}",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue