mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 13:06:03 +10:00
Add Sale page messaging components
This commit is contained in:
parent
154b6d2ecb
commit
07cadc88fe
7 changed files with 1482 additions and 905 deletions
|
|
@ -1,6 +1,7 @@
|
|||
@import '../../marketplace.css';
|
||||
|
||||
.root {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.container {
|
||||
|
|
@ -15,6 +16,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.saleInfo {
|
||||
margin-bottom: 210px;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
max-width: 538px;
|
||||
margin-right: 108px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
|
@ -59,13 +70,6 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.info {
|
||||
@media (--viewportLarge) {
|
||||
margin-right: 132px;
|
||||
max-width: 519px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 22px 24px 0 24px;
|
||||
|
||||
|
|
@ -139,7 +143,7 @@
|
|||
}
|
||||
|
||||
.breakdownContainerMobile {
|
||||
margin: 0 24px 122px 24px;
|
||||
margin: 0 24px 0 24px;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
display: none;
|
||||
|
|
@ -185,6 +189,30 @@
|
|||
margin: 48px;
|
||||
}
|
||||
|
||||
.messagesContainer {
|
||||
margin: 0 24px 0 24px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messagesContainerWithInfoAbove {
|
||||
}
|
||||
|
||||
.messagesHeading {
|
||||
color: var(--matterColorAnti);
|
||||
margin: 48px 0 0 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 48px 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messages {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.actionButtons {
|
||||
/* Position action button row above the footer */
|
||||
z-index: 9;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
ResponsiveImage,
|
||||
PrimaryButton,
|
||||
SecondaryButton,
|
||||
Messages,
|
||||
} from '../../components';
|
||||
|
||||
import css from './SaleDetailsPanel.css';
|
||||
|
|
@ -84,6 +85,7 @@ export const SaleDetailsPanelComponent = props => {
|
|||
const {
|
||||
rootClassName,
|
||||
className,
|
||||
currentUser,
|
||||
transaction,
|
||||
onAcceptSale,
|
||||
onDeclineSale,
|
||||
|
|
@ -141,11 +143,26 @@ export const SaleDetailsPanelComponent = props => {
|
|||
id: 'SaleDetailsPanel.customerBannedStatus',
|
||||
})
|
||||
: saleInfoText(currentTransaction, customerDisplayName);
|
||||
const showInfoMessage = !!infoText;
|
||||
|
||||
const listingTitle = currentListing.attributes.title;
|
||||
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 || fetchMessagesError;
|
||||
// TODO: handle fetchMessagesError
|
||||
const messagesContainer = showMessages ? (
|
||||
<div className={messagesContainerClasses}>
|
||||
<h3 className={css.messagesHeading}>
|
||||
<FormattedMessage id="SaleDetailsPanel.messagesHeading" />
|
||||
</h3>
|
||||
<Messages className={css.messages} messages={messages} currentUser={currentUser} />
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
const canShowButtons = propTypes.txIsPreauthorized(currentTransaction) && !isCustomerBanned;
|
||||
const buttonsDisabled = acceptInProgress || declineInProgress;
|
||||
|
||||
|
|
@ -190,24 +207,24 @@ export const SaleDetailsPanelComponent = props => {
|
|||
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 className={css.saleInfo}>
|
||||
<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={css.avatarWrapper}>
|
||||
<AvatarMedium user={currentCustomer} className={css.avatarMobile} />
|
||||
</div>
|
||||
</div>
|
||||
<div className={css.avatarWrapper}>
|
||||
<AvatarMedium user={currentCustomer} className={css.avatarMobile} />
|
||||
</div>
|
||||
<div className={css.info}>
|
||||
<div className={css.avatarWrapper}>
|
||||
<AvatarLarge user={currentCustomer} className={css.avatarDesktop} />
|
||||
</div>
|
||||
|
|
@ -217,14 +234,15 @@ export const SaleDetailsPanelComponent = props => {
|
|||
{acceptErrorMessage}
|
||||
{declineErrorMessage}
|
||||
</div>
|
||||
<div className={css.breakdownContainerMobile}>
|
||||
<h3 className={css.breakdownTitleMobile}>
|
||||
<FormattedMessage id="SaleDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
{messagesContainer}
|
||||
{actionButtons}
|
||||
</div>
|
||||
<div className={css.breakdownContainerMobile}>
|
||||
<h3 className={css.breakdownTitleMobile}>
|
||||
<FormattedMessage id="SaleDetailsPanel.bookingBreakdownTitle" />
|
||||
</h3>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
<div className={css.breakdownContainerDesktop}>
|
||||
<div className={css.breakdownImageWrapper}>
|
||||
<div className={css.aspectWrapper}>
|
||||
|
|
@ -253,6 +271,7 @@ export const SaleDetailsPanelComponent = props => {
|
|||
SaleDetailsPanelComponent.defaultProps = {
|
||||
rootClassName: null,
|
||||
className: null,
|
||||
currentUser: null,
|
||||
acceptSaleError: null,
|
||||
declineSaleError: null,
|
||||
fetchMessagesError: null,
|
||||
|
|
@ -265,6 +284,7 @@ SaleDetailsPanelComponent.propTypes = {
|
|||
rootClassName: string,
|
||||
className: string,
|
||||
|
||||
currentUser: propTypes.currentUser,
|
||||
transaction: propTypes.transaction.isRequired,
|
||||
onAcceptSale: func.isRequired,
|
||||
onDeclineSale: func.isRequired,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -6,15 +6,14 @@
|
|||
flex: 1;
|
||||
}
|
||||
|
||||
/* actionButtons are fixed positioned until viewportLarge is reached */
|
||||
/* margin-bottom gives space for those buttons when scrolling to bottom */
|
||||
.footerWrapper {
|
||||
margin-bottom: 101px;
|
||||
.footer {
|
||||
display: none;
|
||||
|
||||
@media (--viewportLarge) {
|
||||
margin-bottom: 0;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import classNames from 'classnames';
|
|||
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
||||
import { reset as resetForm } from 'redux-form';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { ensureListing, ensureUser, ensureTransaction } from '../../util/data';
|
||||
import { ensureListing, ensureTransaction } from '../../util/data';
|
||||
import { getMarketplaceEntities } from '../../ducks/marketplaceData.duck';
|
||||
import { isScrollingDisabled } from '../../ducks/UI.duck';
|
||||
import { acceptSale, declineSale, loadData, sendMessage } from './SalePage.duck';
|
||||
|
|
@ -79,18 +79,11 @@ export const SalePageComponent = props => {
|
|||
</p>
|
||||
);
|
||||
|
||||
// We need to know if the customer is in pending state -
|
||||
// to show action buttons bar and reserve space below footer.
|
||||
// (accept reject buttons are position: fixed on mobile layout)
|
||||
const currentCustomer = ensureUser(currentTransaction.customer);
|
||||
const customerLoaded = !!currentCustomer.id;
|
||||
const isCustomerBanned = customerLoaded || currentCustomer.attributes.banned;
|
||||
const isPending = propTypes.txIsPreauthorized(currentTransaction) && !isCustomerBanned;
|
||||
|
||||
const panel =
|
||||
isDataAvailable && currentTransaction.id ? (
|
||||
<SaleDetailsPanel
|
||||
className={detailsClassName}
|
||||
currentUser={currentUser}
|
||||
transaction={currentTransaction}
|
||||
onAcceptSale={onAcceptSale}
|
||||
onDeclineSale={onDeclineSale}
|
||||
|
|
@ -121,7 +114,7 @@ export const SalePageComponent = props => {
|
|||
<LayoutWrapperMain>
|
||||
<div className={css.root}>{panel}</div>
|
||||
</LayoutWrapperMain>
|
||||
<LayoutWrapperFooter className={classNames({ [css.footerWrapper]: isPending })}>
|
||||
<LayoutWrapperFooter className={css.footer}>
|
||||
<Footer />
|
||||
</LayoutWrapperFooter>
|
||||
</LayoutSingleColumn>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,26 @@ exports[`SalePage matches snapshot 1`] = `
|
|||
acceptInProgress={false}
|
||||
acceptSaleError={null}
|
||||
className="undefined"
|
||||
currentUser={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
"banned": false,
|
||||
"email": "provider1@example.com",
|
||||
"emailVerified": true,
|
||||
"profile": Object {
|
||||
"abbreviatedName": "provider1 abbreviated name",
|
||||
"displayName": "provider1 display name",
|
||||
"firstName": "provider1 first name",
|
||||
"lastName": "provider1 last name",
|
||||
},
|
||||
"stripeConnected": true,
|
||||
},
|
||||
"id": UUID {
|
||||
"uuid": "provider1",
|
||||
},
|
||||
"type": "currentUser",
|
||||
}
|
||||
}
|
||||
declineInProgress={false}
|
||||
declineSaleError={null}
|
||||
fetchMessagesError={null}
|
||||
|
|
@ -143,7 +163,7 @@ exports[`SalePage matches snapshot 1`] = `
|
|||
</div>
|
||||
</LayoutWrapperMain>
|
||||
<LayoutWrapperFooter
|
||||
className=""
|
||||
className={null}
|
||||
rootClassName={null}
|
||||
>
|
||||
<InjectIntl(Footer) />
|
||||
|
|
|
|||
|
|
@ -431,6 +431,7 @@
|
|||
"SaleDetailsPanel.listingDeclinedTitle": "{customerName} requested to book {listingLink}",
|
||||
"SaleDetailsPanel.listingDeliveredTitle": "{customerName} booked {listingLink}",
|
||||
"SaleDetailsPanel.listingRequestedTitle": "{customerName} has requested to book {listingLink}",
|
||||
"SaleDetailsPanel.messagesHeading": "Activity",
|
||||
"SaleDetailsPanel.saleAcceptedStatus": "You accepted the request on {formattedDate}.",
|
||||
"SaleDetailsPanel.saleAutoDeclinedStatus": "You did not react to the request on time. The request expired on {formattedDate}.",
|
||||
"SaleDetailsPanel.saleCanceledStatus": "The request was cancelled on {formattedDate}.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue