mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
Send messages from Order page
This commit is contained in:
parent
ff108ca489
commit
a3ca212a24
8 changed files with 263 additions and 156 deletions
|
|
@ -8,4 +8,5 @@
|
|||
height: 28px;
|
||||
|
||||
stroke: var(--marketplaceColor);
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ const IconSpinner = props => {
|
|||
<svg
|
||||
className={classes}
|
||||
viewBox="0 0 30 30"
|
||||
strokeWidth="3"
|
||||
preserveAspectRatio="xMidYMid"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export const MessagesComponent = props => {
|
|||
return (
|
||||
<ul className={classes}>
|
||||
{messages.map(m => (
|
||||
<li key={m.id.uuid} className={css.messageItem}>
|
||||
<li id={`msg-${m.id.uuid}`} key={m.id.uuid} className={css.messageItem}>
|
||||
{msg(m)}
|
||||
</li>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
|
|
@ -78,141 +78,136 @@ const orderMessage = (transaction, providerName) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
export const OrderDetailsPanelComponent = 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);
|
||||
const currentCustomer = ensureUser(currentTransaction.customer);
|
||||
|
||||
const listingLoaded = !!currentListing.id;
|
||||
const listingDeleted = listingLoaded && currentListing.attributes.deleted;
|
||||
|
||||
const bannedUserDisplayName = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.bannedUserDisplayName',
|
||||
});
|
||||
const deletedListingTitle = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.deletedListingTitle',
|
||||
});
|
||||
const deletedListingOrderTitle = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.deletedListingOrderTitle',
|
||||
});
|
||||
const orderMessageDeletedListing = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.messageDeletedListing',
|
||||
});
|
||||
|
||||
const authorDisplayName = userDisplayName(currentProvider, bannedUserDisplayName);
|
||||
const customerDisplayName = userDisplayName(currentCustomer, bannedUserDisplayName);
|
||||
|
||||
let listingLink = null;
|
||||
|
||||
if (listingLoaded && currentListing.attributes.title) {
|
||||
const title = currentListing.attributes.title;
|
||||
const params = { id: currentListing.id.uuid, slug: createSlug(title) };
|
||||
listingLink = (
|
||||
<NamedLink name="ListingPage" params={params}>
|
||||
{title}
|
||||
</NamedLink>
|
||||
);
|
||||
} else {
|
||||
listingLink = deletedListingOrderTitle;
|
||||
export class OrderDetailsPanelComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { setInitialEmptyMessage: false };
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
currentUser,
|
||||
transaction,
|
||||
messages,
|
||||
initialMessageFailed,
|
||||
fetchMessagesError,
|
||||
sendMessageInProgress,
|
||||
sendMessageError,
|
||||
onSendMessage,
|
||||
onResetForm,
|
||||
intl,
|
||||
} = this.props;
|
||||
|
||||
const listingTitle = currentListing.attributes.deleted
|
||||
? deletedListingTitle
|
||||
: currentListing.attributes.title;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const currentProvider = ensureUser(currentTransaction.provider);
|
||||
const currentCustomer = ensureUser(currentTransaction.customer);
|
||||
|
||||
const bookingInfo = breakdown(currentTransaction);
|
||||
const orderHeading = orderTitle(currentTransaction, listingLink, customerDisplayName);
|
||||
const orderInfoText = listingDeleted
|
||||
? orderMessageDeletedListing
|
||||
: orderMessage(currentTransaction, authorDisplayName);
|
||||
const showInfoMessage = !!orderInfoText;
|
||||
const listingLoaded = !!currentListing.id;
|
||||
const listingDeleted = listingLoaded && currentListing.attributes.deleted;
|
||||
|
||||
const firstImage =
|
||||
currentListing.images && currentListing.images.length > 0 ? currentListing.images[0] : null;
|
||||
const bannedUserDisplayName = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.bannedUserDisplayName',
|
||||
});
|
||||
const deletedListingTitle = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.deletedListingTitle',
|
||||
});
|
||||
const deletedListingOrderTitle = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.deletedListingOrderTitle',
|
||||
});
|
||||
const orderMessageDeletedListing = intl.formatMessage({
|
||||
id: 'OrderDetailsPanel.messageDeletedListing',
|
||||
});
|
||||
|
||||
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 authorDisplayName = userDisplayName(currentProvider, bannedUserDisplayName);
|
||||
const customerDisplayName = userDisplayName(currentCustomer, bannedUserDisplayName);
|
||||
|
||||
const sendMessagePlaceholder = intl.formatMessage(
|
||||
{ id: 'OrderDetailsPanel.sendMessagePlaceholder' },
|
||||
{ name: 'Juho' }
|
||||
);
|
||||
const sendMessageForm = (
|
||||
<SendMessageForm
|
||||
rootClassName={css.sendMessageForm}
|
||||
messagePlaceholder={sendMessagePlaceholder}
|
||||
/>
|
||||
);
|
||||
let listingLink = null;
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
if (listingLoaded && currentListing.attributes.title) {
|
||||
const title = currentListing.attributes.title;
|
||||
const params = { id: currentListing.id.uuid, slug: createSlug(title) };
|
||||
listingLink = (
|
||||
<NamedLink name="ListingPage" params={params}>
|
||||
{title}
|
||||
</NamedLink>
|
||||
);
|
||||
} else {
|
||||
listingLink = deletedListingOrderTitle;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={css.container}>
|
||||
<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>
|
||||
{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}
|
||||
{sendMessageForm}
|
||||
</div>
|
||||
<div className={css.bookingBreakdownContainer}>
|
||||
<div className={css.breakdownDesktop}>
|
||||
<div className={css.breakdownImageWrapper}>
|
||||
const listingTitle = currentListing.attributes.deleted
|
||||
? deletedListingTitle
|
||||
: currentListing.attributes.title;
|
||||
|
||||
const bookingInfo = breakdown(currentTransaction);
|
||||
const orderHeading = orderTitle(currentTransaction, listingLink, customerDisplayName);
|
||||
const orderInfoText = listingDeleted
|
||||
? orderMessageDeletedListing
|
||||
: 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 sendMessagePlaceholder = intl.formatMessage(
|
||||
{ id: 'OrderDetailsPanel.sendMessagePlaceholder' },
|
||||
{ name: 'Juho' }
|
||||
);
|
||||
|
||||
const sendMessageFormName = 'OrderDetailsPanel.SendMessageForm';
|
||||
const scrollToMessage = messageId => {
|
||||
const selector = `#msg-${messageId.uuid}`;
|
||||
const el = document.querySelector(selector);
|
||||
if (el) {
|
||||
el.scrollIntoView({
|
||||
block: 'start',
|
||||
behavior: 'smooth',
|
||||
});
|
||||
}
|
||||
};
|
||||
const handleMessageSubmit = values => {
|
||||
return onSendMessage(currentTransaction.id, values.message)
|
||||
.then(messageId => {
|
||||
onResetForm(sendMessageFormName);
|
||||
scrollToMessage(messageId);
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e);
|
||||
});
|
||||
};
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={css.container}>
|
||||
<div className={css.orderInfo}>
|
||||
<div className={css.imageWrapperMobile}>
|
||||
<div className={css.aspectWrapper}>
|
||||
<ResponsiveImage
|
||||
rootClassName={css.rootForImage}
|
||||
|
|
@ -222,40 +217,80 @@ export const OrderDetailsPanelComponent = props => {
|
|||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100%"
|
||||
sizes="100vw"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.avatarWrapper}>
|
||||
<div className={classNames(css.avatarWrapper, css.avatarMobile)}>
|
||||
<AvatarMedium user={currentProvider} />
|
||||
</div>
|
||||
<div className={css.breakdownHeadings}>
|
||||
<h2 className={css.breakdownTitle}>{listingTitle}</h2>
|
||||
<p className={css.breakdownSubtitle}>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.hostedBy"
|
||||
values={{ name: authorDisplayName }}
|
||||
/>
|
||||
</p>
|
||||
<h1 className={css.heading}>{orderHeading}</h1>
|
||||
{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}
|
||||
<SendMessageForm
|
||||
form={sendMessageFormName}
|
||||
rootClassName={css.sendMessageForm}
|
||||
messagePlaceholder={sendMessagePlaceholder}
|
||||
inProgress={sendMessageInProgress}
|
||||
sendMessageError={sendMessageError}
|
||||
onSubmit={handleMessageSubmit}
|
||||
/>
|
||||
</div>
|
||||
<div className={css.bookingBreakdownContainer}>
|
||||
<div className={css.breakdownDesktop}>
|
||||
<div className={css.breakdownImageWrapper}>
|
||||
<div className={css.aspectWrapper}>
|
||||
<ResponsiveImage
|
||||
rootClassName={css.rootForImage}
|
||||
alt={listingTitle}
|
||||
image={firstImage}
|
||||
nameSet={[
|
||||
{ name: 'landscape-crop', size: '400w' },
|
||||
{ name: 'landscape-crop2x', size: '800w' },
|
||||
]}
|
||||
sizes="100%"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.avatarWrapper}>
|
||||
<AvatarMedium user={currentProvider} />
|
||||
</div>
|
||||
<div className={css.breakdownHeadings}>
|
||||
<h2 className={css.breakdownTitle}>{listingTitle}</h2>
|
||||
<p className={css.breakdownSubtitle}>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.hostedBy"
|
||||
values={{ name: authorDisplayName }}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<h3 className={css.bookingBreakdownTitle}>
|
||||
<FormattedMessage id="OrderDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
<h3 className={css.bookingBreakdownTitle}>
|
||||
<FormattedMessage id="OrderDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
OrderDetailsPanelComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
fetchMessagesError: null,
|
||||
sendMessageError: null,
|
||||
};
|
||||
|
||||
const { string, arrayOf, bool } = PropTypes;
|
||||
const { string, arrayOf, bool, func } = PropTypes;
|
||||
|
||||
OrderDetailsPanelComponent.propTypes = {
|
||||
rootClassName: string,
|
||||
|
|
@ -266,6 +301,10 @@ OrderDetailsPanelComponent.propTypes = {
|
|||
messages: arrayOf(propTypes.message).isRequired,
|
||||
initialMessageFailed: bool.isRequired,
|
||||
fetchMessagesError: propTypes.error,
|
||||
sendMessageInProgress: bool.isRequired,
|
||||
sendMessageError: propTypes.error,
|
||||
onSendMessage: func.isRequired,
|
||||
onResetForm: func.isRequired,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ export const FETCH_MESSAGES_REQUEST = 'app/OrderPage/FETCH_MESSAGES_REQUEST';
|
|||
export const FETCH_MESSAGES_SUCCESS = 'app/OrderPage/FETCH_MESSAGES_SUCCESS';
|
||||
export const FETCH_MESSAGES_ERROR = 'app/OrderPage/FETCH_MESSAGES_ERROR';
|
||||
|
||||
export const SEND_MESSAGE_REQUEST = 'app/OrderPage/SEND_MESSAGE_REQUEST';
|
||||
export const SEND_MESSAGE_SUCCESS = 'app/OrderPage/SEND_MESSAGE_SUCCESS';
|
||||
export const SEND_MESSAGE_ERROR = 'app/OrderPage/SEND_MESSAGE_ERROR';
|
||||
|
||||
// ================ Reducer ================ //
|
||||
|
||||
const initialState = {
|
||||
|
|
@ -26,6 +30,8 @@ const initialState = {
|
|||
fetchMessagesError: null,
|
||||
messages: [],
|
||||
messageSendingFailedToTransaction: null,
|
||||
sendMessageInProgress: false,
|
||||
sendMessageError: null,
|
||||
};
|
||||
|
||||
export default function checkoutPageReducer(state = initialState, action = {}) {
|
||||
|
|
@ -43,6 +49,7 @@ export default function checkoutPageReducer(state = initialState, action = {}) {
|
|||
case FETCH_ORDER_ERROR:
|
||||
console.error(payload); // eslint-disable-line
|
||||
return { ...state, fetchOrderInProgress: false, fetchOrderError: payload };
|
||||
|
||||
case FETCH_MESSAGES_REQUEST:
|
||||
return { ...state, fetchMessagesInProgress: true, fetchMessagesError: null };
|
||||
case FETCH_MESSAGES_SUCCESS:
|
||||
|
|
@ -50,6 +57,13 @@ export default function checkoutPageReducer(state = initialState, action = {}) {
|
|||
case FETCH_MESSAGES_ERROR:
|
||||
return { ...state, fetchMessagesInProgress: false, fetchMessagesError: payload };
|
||||
|
||||
case SEND_MESSAGE_REQUEST:
|
||||
return { ...state, sendMessageInProgress: true, sendMessageError: null };
|
||||
case SEND_MESSAGE_SUCCESS:
|
||||
return { ...state, sendMessageInProgress: false };
|
||||
case SEND_MESSAGE_ERROR:
|
||||
return { ...state, sendMessageInProgress: false, sendMessageError: payload };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
@ -70,6 +84,10 @@ const fetchMessagesRequest = () => ({ type: FETCH_MESSAGES_REQUEST });
|
|||
const fetchMessagesSuccess = messages => ({ type: FETCH_MESSAGES_SUCCESS, payload: messages });
|
||||
const fetchMessagesError = e => ({ type: FETCH_MESSAGES_ERROR, error: true, payload: e });
|
||||
|
||||
const sendMessageRequest = () => ({ type: SEND_MESSAGE_REQUEST });
|
||||
const sendMessageSuccess = () => ({ type: SEND_MESSAGE_SUCCESS });
|
||||
const sendMessageError = e => ({ type: SEND_MESSAGE_ERROR, error: true, payload: e });
|
||||
|
||||
// ================ Thunks ================ //
|
||||
|
||||
const listingRelationship = txResponse => {
|
||||
|
|
@ -130,7 +148,7 @@ export const fetchMessages = txId => (dispatch, getState, sdk) => {
|
|||
dispatch(fetchMessagesSuccess(denormalized));
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(fetchMessagesError(e));
|
||||
dispatch(fetchMessagesError(storableError(e)));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
@ -140,6 +158,32 @@ export const fetchMessages = txId => (dispatch, getState, sdk) => {
|
|||
export const loadData = params => dispatch => {
|
||||
const orderId = new types.UUID(params.id);
|
||||
|
||||
// Clear the send error since the message form is emptied as well.
|
||||
dispatch(setInitialValues({ sendMessageError: null }));
|
||||
|
||||
// Order (i.e. transaction entity in API, but from buyers perspective) contains order details
|
||||
return Promise.all([dispatch(fetchOrder(orderId)), dispatch(fetchMessages(orderId))]);
|
||||
};
|
||||
|
||||
export const sendMessage = (orderId, message) => (dispatch, getState, sdk) => {
|
||||
console.log('sendMessage:', orderId, message);
|
||||
dispatch(sendMessageRequest());
|
||||
|
||||
return sdk.messages
|
||||
.send({ transactionId: orderId, content: message })
|
||||
.then(response => {
|
||||
const messageId = response.data.data.id;
|
||||
return dispatch(fetchMessages(orderId))
|
||||
.then(() => {
|
||||
dispatch(sendMessageSuccess());
|
||||
return messageId;
|
||||
})
|
||||
.catch(() => dispatch(sendMessageSuccess()));
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(sendMessageError(storableError(e)));
|
||||
// Rethrow so the page can track whether the sending failed, and
|
||||
// keep the message in the form for a retry.
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { compose } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { reset as resetForm } from 'redux-form';
|
||||
import classNames from 'classnames';
|
||||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
|
|
@ -20,7 +21,7 @@ import {
|
|||
} from '../../components';
|
||||
import { TopbarContainer } from '../../containers';
|
||||
|
||||
import { loadData, setInitialValues } from './OrderPage.duck';
|
||||
import { loadData, setInitialValues, sendMessage } from './OrderPage.duck';
|
||||
import css from './OrderPage.css';
|
||||
|
||||
// OrderPage handles data loading
|
||||
|
|
@ -32,6 +33,10 @@ export const OrderPageComponent = props => {
|
|||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
sendMessageInProgress,
|
||||
sendMessageError,
|
||||
onSendMessage,
|
||||
onResetForm,
|
||||
intl,
|
||||
params,
|
||||
scrollingDisabled,
|
||||
|
|
@ -84,6 +89,10 @@ export const OrderPageComponent = props => {
|
|||
messages={messages}
|
||||
initialMessageFailed={initialMessageFailed}
|
||||
fetchMessagesError={fetchMessagesError}
|
||||
sendMessageInProgress={sendMessageInProgress}
|
||||
sendMessageError={sendMessageError}
|
||||
onSendMessage={onSendMessage}
|
||||
onResetForm={onResetForm}
|
||||
/>
|
||||
) : (
|
||||
loadingOrFaildFetching
|
||||
|
|
@ -112,10 +121,11 @@ OrderPageComponent.defaultProps = {
|
|||
fetchOrderError: null,
|
||||
fetchMessagesError: null,
|
||||
messageSendingFailedToTransaction: null,
|
||||
sendMessageError: null,
|
||||
transaction: null,
|
||||
};
|
||||
|
||||
const { bool, oneOf, shape, string, array } = PropTypes;
|
||||
const { bool, oneOf, shape, string, array, func } = PropTypes;
|
||||
|
||||
OrderPageComponent.propTypes = {
|
||||
params: shape({ id: string }).isRequired,
|
||||
|
|
@ -126,8 +136,12 @@ OrderPageComponent.propTypes = {
|
|||
fetchMessagesError: propTypes.error,
|
||||
messages: array.isRequired,
|
||||
messageSendingFailedToTransaction: propTypes.uuid,
|
||||
sendMessageInProgress: bool.isRequired,
|
||||
sendMessageError: propTypes.error,
|
||||
scrollingDisabled: bool.isRequired,
|
||||
transaction: propTypes.transaction,
|
||||
onSendMessage: func.isRequired,
|
||||
onResetForm: func.isRequired,
|
||||
|
||||
// from injectIntl
|
||||
intl: intlShape.isRequired,
|
||||
|
|
@ -141,6 +155,8 @@ const mapStateToProps = state => {
|
|||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
sendMessageInProgress,
|
||||
sendMessageError,
|
||||
} = state.OrderPage;
|
||||
const transactions = getMarketplaceEntities(state, transactionRef ? [transactionRef] : []);
|
||||
const transaction = transactions.length > 0 ? transactions[0] : null;
|
||||
|
|
@ -151,12 +167,21 @@ const mapStateToProps = state => {
|
|||
fetchMessagesError,
|
||||
messages,
|
||||
messageSendingFailedToTransaction,
|
||||
sendMessageInProgress,
|
||||
sendMessageError,
|
||||
scrollingDisabled: isScrollingDisabled(state),
|
||||
transaction,
|
||||
};
|
||||
};
|
||||
|
||||
const OrderPage = compose(connect(mapStateToProps), injectIntl)(OrderPageComponent);
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onSendMessage: (orderId, message) => dispatch(sendMessage(orderId, message)),
|
||||
onResetForm: formName => dispatch(resetForm(formName)),
|
||||
});
|
||||
|
||||
const OrderPage = compose(connect(mapStateToProps, mapDispatchToProps), injectIntl)(
|
||||
OrderPageComponent
|
||||
);
|
||||
|
||||
OrderPage.setInitialValues = setInitialValues;
|
||||
OrderPage.loadData = loadData;
|
||||
|
|
|
|||
|
|
@ -100,8 +100,6 @@ class SendMessageFormComponent extends Component {
|
|||
invalid,
|
||||
} = this.props;
|
||||
|
||||
console.log({ sendMessageError });
|
||||
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
const submitInProgress = submitting || inProgress;
|
||||
const submitDisabled = invalid || submitInProgress;
|
||||
|
|
|
|||
|
|
@ -62,12 +62,13 @@ export const createResourceLocatorString = (
|
|||
routeName,
|
||||
routes,
|
||||
pathParams = {},
|
||||
searchParams = {}
|
||||
searchParams = {},
|
||||
hash = ''
|
||||
) => {
|
||||
const searchQuery = stringify(searchParams);
|
||||
const includeSearchQuery = searchQuery.length > 0 ? `?${searchQuery}` : '';
|
||||
const path = pathByRouteName(routeName, routes, pathParams);
|
||||
return `${path}${includeSearchQuery}`;
|
||||
return `${path}${includeSearchQuery}${hash}`;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue