mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-30 18:16:48 +10:00
Merge pull request #129 from sharetribe/provider-accepts
Provider accepts
This commit is contained in:
commit
70990f4048
18 changed files with 240 additions and 65 deletions
|
|
@ -13,7 +13,16 @@ import { types } from '../../util/sdkLoader';
|
|||
import css from './BookingInfo.css';
|
||||
|
||||
const BookingInfoComponent = props => {
|
||||
const { bookingStart, bookingEnd, className, commission, intl, subtotalPrice, totalPrice, unitPrice } = props;
|
||||
const {
|
||||
bookingStart,
|
||||
bookingEnd,
|
||||
className,
|
||||
commission,
|
||||
intl,
|
||||
subtotalPrice,
|
||||
totalPrice,
|
||||
unitPrice,
|
||||
} = props;
|
||||
|
||||
const hasSelectedNights = bookingStart && bookingEnd;
|
||||
|
||||
|
|
@ -22,17 +31,21 @@ const BookingInfoComponent = props => {
|
|||
return <div className={classNames(css.container, className)} />;
|
||||
}
|
||||
|
||||
const bookingPeriod = <FormattedMessage
|
||||
id="BookingInfo.bookingPeriod"
|
||||
values={{
|
||||
bookingStart: intl.formatDate(bookingStart),
|
||||
bookingEnd: intl.formatDate(bookingEnd),
|
||||
}}
|
||||
/>;
|
||||
const bookingPeriod = (
|
||||
<FormattedMessage
|
||||
id="BookingInfo.bookingPeriod"
|
||||
values={{
|
||||
bookingStart: intl.formatDate(bookingStart),
|
||||
bookingEnd: intl.formatDate(bookingEnd),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
// diff gives night count between dates
|
||||
const nightCount = moment(bookingEnd).diff(moment(bookingStart), 'days');
|
||||
const nightCountMessage = <FormattedMessage id="BookingInfo.nightCount" values={{ count: nightCount }} />;
|
||||
const nightCountMessage = (
|
||||
<FormattedMessage id="BookingInfo.nightCount" values={{ count: nightCount }} />
|
||||
);
|
||||
|
||||
const currencyConfig = config.currencyConfig;
|
||||
const subUnitDivisor = currencyConfig.subUnitDivisor;
|
||||
|
|
@ -79,7 +92,7 @@ const BookingInfoComponent = props => {
|
|||
const commisionInfo = commission
|
||||
? <div className={css.row}>
|
||||
<div className={css.commissionLabel}>
|
||||
<FormattedMessage id="BookingInfo.commission" />
|
||||
<FormattedMessage id="BookingInfo.commission" values={{ marketplace: 'Saunatime' }} />
|
||||
</div>
|
||||
<div className={css.commission}>
|
||||
{formattedCommission}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ exports[`BookingInfo provider transaction data matches snapshot 1`] = `
|
|||
<div
|
||||
className={undefined}>
|
||||
<span>
|
||||
Charged commission:
|
||||
Saunatime fee:
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
margin: 1rem 1rem 2rem 1rem;
|
||||
}
|
||||
|
||||
.messagesContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
margin: 1rem 1rem 2rem 1rem;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedDate, FormattedMessage } from 'react-intl';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { createSlug } from '../../util/urlHelpers';
|
||||
import { types } from '../../util/sdkLoader';
|
||||
|
|
@ -8,7 +8,15 @@ import { Avatar, BookingInfo, NamedLink } from '../../components';
|
|||
import css from './OrderDetailsPanel.css';
|
||||
|
||||
const OrderDetailsPanel = props => {
|
||||
const { className, totalPrice, orderState, booking, listing, provider } = props;
|
||||
const {
|
||||
className,
|
||||
totalPrice,
|
||||
orderState,
|
||||
lastTransitionedAt,
|
||||
booking,
|
||||
listing,
|
||||
provider,
|
||||
} = props;
|
||||
const { firstName, lastName } = provider.attributes.profile;
|
||||
const providerName = firstName ? `${firstName} ${lastName}` : '';
|
||||
|
||||
|
|
@ -19,24 +27,6 @@ const OrderDetailsPanel = props => {
|
|||
</NamedLink>
|
||||
);
|
||||
|
||||
const title = orderState === propTypes.TX_STATE_PREAUTHORIZED
|
||||
? <FormattedMessage
|
||||
id="OrderDetailsPanel.listingTitle"
|
||||
values={{ title: listingLink }}
|
||||
/>
|
||||
: null;
|
||||
|
||||
const message = orderState === propTypes.TX_STATE_PREAUTHORIZED
|
||||
? <div className={css.message}>
|
||||
<div className={css.avatarWrapper}>
|
||||
<Avatar name={providerName} />
|
||||
</div>
|
||||
<div>
|
||||
<FormattedMessage id="OrderDetailsPanel.orderStatusMessage" values={{ providerName }} />
|
||||
</div>
|
||||
</div>
|
||||
: null;
|
||||
|
||||
// TODO We can't use price from listing, since that might have changed.
|
||||
// When API includes unit price and possible additional fees, we need to change this.
|
||||
const unitPrice = listing.attributes.price;
|
||||
|
|
@ -51,10 +41,59 @@ const OrderDetailsPanel = props => {
|
|||
/>
|
||||
: <p className={css.error}>{'priceRequiredMessage'}</p>;
|
||||
|
||||
// orderState affects to both title and message section
|
||||
let stateMsgData = {};
|
||||
switch (orderState) {
|
||||
case propTypes.TX_STATE_PREAUTHORIZED:
|
||||
stateMsgData = {
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderRequestedTitle"
|
||||
values={{ title: listingLink }}
|
||||
/>
|
||||
),
|
||||
message: (
|
||||
<div className={css.messagesContainer}>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderRequestedStatus"
|
||||
values={{ providerName }}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
break;
|
||||
case propTypes.TX_STATE_ACCEPTED:
|
||||
stateMsgData = {
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAcceptedTitle"
|
||||
values={{ title: listingLink }}
|
||||
/>
|
||||
),
|
||||
message: (
|
||||
<div className={css.messagesContainer}>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderAcceptedStatus"
|
||||
values={{ providerName }}
|
||||
/>
|
||||
<FormattedDate value={lastTransitionedAt} year="numeric" month="short" day="numeric" />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
stateMsgData = { title: null, message: null };
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<h1 className={css.title}>{title}</h1>
|
||||
{message}
|
||||
<h1 className={css.title}>{stateMsgData.title}</h1>
|
||||
<div className={css.message}>
|
||||
<div className={css.avatarWrapper}>
|
||||
<Avatar name={providerName} />
|
||||
</div>
|
||||
{stateMsgData.message}
|
||||
</div>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -68,6 +107,7 @@ OrderDetailsPanel.propTypes = {
|
|||
className: string,
|
||||
totalPrice: instanceOf(types.Money).isRequired,
|
||||
orderState: string.isRequired,
|
||||
lastTransitionedAt: instanceOf(Date).isRequired,
|
||||
booking: propTypes.booking.isRequired,
|
||||
listing: propTypes.listing.isRequired,
|
||||
provider: propTypes.user.isRequired,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ describe('OrderDetailsPanel', () => {
|
|||
commission: null,
|
||||
totalPrice: new Money(16500, 'USD'),
|
||||
orderState: 'state/preauthorized',
|
||||
lastTransitionedAt: new Date(Date.UTC(2017, 5, 10)),
|
||||
booking: createBooking(
|
||||
'booking1',
|
||||
new Date(Date.UTC(2017, 5, 10)),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ exports[`OrderDetailsPanel matches snapshot 1`] = `
|
|||
className={null}>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.listingTitle"
|
||||
id="OrderDetailsPanel.orderRequestedTitle"
|
||||
values={
|
||||
Object {
|
||||
"title": <withFlattenedRoutes(withRouter(NamedLink))
|
||||
|
|
@ -27,7 +27,7 @@ exports[`OrderDetailsPanel matches snapshot 1`] = `
|
|||
</div>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="OrderDetailsPanel.orderStatusMessage"
|
||||
id="OrderDetailsPanel.orderRequestedStatus"
|
||||
values={
|
||||
Object {
|
||||
"providerName": "provider first name provider last name",
|
||||
|
|
|
|||
|
|
@ -5,8 +5,13 @@
|
|||
padding: 3rem 2rem;
|
||||
}
|
||||
|
||||
.title,
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { PropTypes } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { FormattedDate, FormattedMessage } from 'react-intl';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { types } from '../../util/sdkLoader';
|
||||
import { createSlug } from '../../util/urlHelpers';
|
||||
|
|
@ -8,7 +8,16 @@ import { Avatar, BookingInfo, NamedLink } from '../../components';
|
|||
import css from './SaleDetailsPanel.css';
|
||||
|
||||
const SaleDetailsPanel = props => {
|
||||
const { className, subtotalPrice, saleState, booking, listing, customer, commission } = props;
|
||||
const {
|
||||
className,
|
||||
subtotalPrice,
|
||||
saleState,
|
||||
booking,
|
||||
lastTransitionedAt,
|
||||
listing,
|
||||
customer,
|
||||
commission,
|
||||
} = props;
|
||||
const { firstName, lastName } = customer.attributes.profile;
|
||||
const customerName = firstName ? `${firstName} ${lastName}` : '';
|
||||
|
||||
|
|
@ -19,19 +28,6 @@ const SaleDetailsPanel = props => {
|
|||
</NamedLink>
|
||||
);
|
||||
|
||||
const title = saleState === propTypes.TX_STATE_PREAUTHORIZED
|
||||
? <FormattedMessage
|
||||
id="SaleDetailsPanel.listingTitle"
|
||||
values={{ customerName: customerName, title: listingLink }}
|
||||
/>
|
||||
: null;
|
||||
|
||||
const message = saleState === propTypes.TX_STATE_PREAUTHORIZED
|
||||
? <div className={css.message}>
|
||||
<FormattedMessage id="SaleDetailsPanel.saleStatusMessage" values={{ customerName }} />
|
||||
</div>
|
||||
: null;
|
||||
|
||||
// TODO We can't use price from listing, since that might have changed.
|
||||
// When API includes unit price and possible additional fees, we need to change this.
|
||||
const unitPrice = listing.attributes.price;
|
||||
|
|
@ -47,14 +43,54 @@ const SaleDetailsPanel = props => {
|
|||
/>
|
||||
: <p className={css.error}>{'priceRequiredMessage'}</p>;
|
||||
|
||||
// saleState affects to both title and message section
|
||||
let stateMsgData = {};
|
||||
switch (saleState) {
|
||||
case propTypes.TX_STATE_PREAUTHORIZED:
|
||||
stateMsgData = {
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.listingRequestedTitle"
|
||||
values={{ customerName: customerName, title: listingLink }}
|
||||
/>
|
||||
),
|
||||
message: (
|
||||
<div className={css.message}>
|
||||
<FormattedMessage id="SaleDetailsPanel.saleRequestedStatus" values={{ customerName }} />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
break;
|
||||
case propTypes.TX_STATE_ACCEPTED:
|
||||
stateMsgData = {
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.listingAcceptedTitle"
|
||||
values={{ customerName: customerName, title: listingLink }}
|
||||
/>
|
||||
),
|
||||
message: (
|
||||
<div className={css.message}>
|
||||
<FormattedMessage id="SaleDetailsPanel.saleAcceptedStatus" />
|
||||
<FormattedDate value={lastTransitionedAt} year="numeric" month="short" day="numeric" />
|
||||
</div>
|
||||
),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
stateMsgData = { title: null, message: null };
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={css.messagesContainer}>
|
||||
<div className={css.avatarWrapper}>
|
||||
<Avatar name={customerName} />
|
||||
</div>
|
||||
<h1 className={css.title}>{title}</h1>
|
||||
{message}
|
||||
<h1 className={css.title}>
|
||||
{stateMsgData.title}
|
||||
</h1>
|
||||
{stateMsgData.message}
|
||||
</div>
|
||||
{bookingInfo}
|
||||
</div>
|
||||
|
|
@ -70,6 +106,7 @@ SaleDetailsPanel.propTypes = {
|
|||
subtotalPrice: instanceOf(types.Money).isRequired,
|
||||
commission: instanceOf(types.Money).isRequired,
|
||||
saleState: string.isRequired,
|
||||
lastTransitionedAt: instanceOf(Date).isRequired,
|
||||
booking: propTypes.booking.isRequired,
|
||||
listing: propTypes.listing.isRequired,
|
||||
customer: propTypes.user.isRequired,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ describe('SaleDetailsPanel', () => {
|
|||
commission: new Money(1650, 'USD'),
|
||||
subtotalPrice: new Money(16500, 'USD'),
|
||||
saleState: 'state/preauthorized',
|
||||
lastTransitionedAt: new Date(Date.UTC(2017, 5, 10)),
|
||||
booking: createBooking(
|
||||
'booking1',
|
||||
new Date(Date.UTC(2017, 5, 10)),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ exports[`SaleDetailsPanel matches snapshot 1`] = `
|
|||
</div>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.listingTitle"
|
||||
id="SaleDetailsPanel.listingRequestedTitle"
|
||||
values={
|
||||
Object {
|
||||
"customerName": "customer1 first name customer1 last name",
|
||||
|
|
@ -28,7 +28,7 @@ exports[`SaleDetailsPanel matches snapshot 1`] = `
|
|||
</h1>
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.saleStatusMessage"
|
||||
id="SaleDetailsPanel.saleRequestedStatus"
|
||||
values={
|
||||
Object {
|
||||
"customerName": "customer1 first name customer1 last name",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export const OrderPageComponent = props => {
|
|||
const detailsProps = {
|
||||
totalPrice: currentTransaction.attributes.total,
|
||||
orderState: currentTransaction.attributes.state,
|
||||
lastTransitionedAt: currentTransaction.attributes.lastTransitionedAt,
|
||||
listing: currentListing,
|
||||
booking: ensureBooking(currentTransaction.booking),
|
||||
provider: ensureUser(currentTransaction.provider),
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ exports[`OrderPage matches snapshot 1`] = `
|
|||
}
|
||||
}
|
||||
className="undefined"
|
||||
lastTransitionedAt={2017-06-01T00:00:00.000Z}
|
||||
listing={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
.actionButtons,
|
||||
.title {
|
||||
margin: 1rem 1rem 2rem 1rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,18 +2,26 @@ import { types } from '../../util/sdkLoader';
|
|||
import { addEntities } from '../../ducks/sdk.duck';
|
||||
import { fetchCurrentUser } from '../../ducks/user.duck';
|
||||
|
||||
// Transition-to keys
|
||||
const TRANSITION_ACCEPT = 'transition/accept';
|
||||
|
||||
// ================ Action types ================ //
|
||||
|
||||
export const FETCH_SALE_REQUEST = 'app/InboxPage/FETCH_SALE_REQUEST';
|
||||
export const FETCH_SALE_SUCCESS = 'app/InboxPage/FETCH_SALE_SUCCESS';
|
||||
export const FETCH_SALE_ERROR = 'app/InboxPage/FETCH_SALE_ERROR';
|
||||
|
||||
export const ACCEPT_SALE_REQUEST = 'app/InboxPage/ACCEPT_SALE_REQUEST';
|
||||
export const ACCEPT_SALE_SUCCESS = 'app/InboxPage/ACCEPT_SALE_SUCCESS';
|
||||
export const ACCEPT_SALE_ERROR = 'app/InboxPage/ACCEPT_SALE_ERROR';
|
||||
// ================ Reducer ================ //
|
||||
|
||||
const initialState = {
|
||||
fetchInProgress: false,
|
||||
fetchSaleError: null,
|
||||
transactionRef: null,
|
||||
acceptOrRejectInProgress: false,
|
||||
acceptSaleError: null,
|
||||
};
|
||||
|
||||
export default function checkoutPageReducer(state = initialState, action = {}) {
|
||||
|
|
@ -29,6 +37,14 @@ export default function checkoutPageReducer(state = initialState, action = {}) {
|
|||
console.error(payload); // eslint-disable-line
|
||||
return { ...state, fetchInProgress: false, fetchSaleError: payload };
|
||||
|
||||
case ACCEPT_SALE_REQUEST:
|
||||
return { ...state, acceptOrRejectInProgress: true, acceptSaleError: null };
|
||||
case ACCEPT_SALE_SUCCESS:
|
||||
return { ...state, acceptOrRejectInProgress: false };
|
||||
case ACCEPT_SALE_ERROR:
|
||||
console.error(payload); // eslint-disable-line
|
||||
return { ...state, acceptOrRejectInProgress: false, acceptSaleError: payload };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
@ -40,6 +56,10 @@ const fetchSaleRequest = () => ({ type: FETCH_SALE_REQUEST });
|
|||
const fetchSaleSuccess = response => ({ type: FETCH_SALE_SUCCESS, payload: response });
|
||||
const fetchSaleError = e => ({ type: FETCH_SALE_ERROR, error: true, payload: e });
|
||||
|
||||
const acceptSaleRequest = () => ({ type: ACCEPT_SALE_REQUEST });
|
||||
const acceptSaleSuccess = () => ({ type: ACCEPT_SALE_SUCCESS });
|
||||
const acceptSaleError = e => ({ type: ACCEPT_SALE_ERROR, error: true, payload: e });
|
||||
|
||||
// ================ Thunks ================ //
|
||||
|
||||
export const fetchSale = id =>
|
||||
|
|
@ -59,6 +79,23 @@ export const fetchSale = id =>
|
|||
});
|
||||
};
|
||||
|
||||
export const acceptSale = id =>
|
||||
(dispatch, getState, sdk) => {
|
||||
dispatch(acceptSaleRequest());
|
||||
|
||||
return sdk.transactions
|
||||
.transition({ id, transition: TRANSITION_ACCEPT, params: {} }, { expand: true })
|
||||
.then(response => {
|
||||
dispatch(addEntities(response));
|
||||
dispatch(acceptSaleSuccess());
|
||||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(acceptSaleError(e));
|
||||
throw 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 =>
|
||||
|
|
|
|||
|
|
@ -4,16 +4,16 @@ import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
|
|||
import { connect } from 'react-redux';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import { ensureBooking, ensureListing, ensureTransaction, ensureUser } from '../../util/data';
|
||||
import { SaleDetailsPanel, PageLayout } from '../../components';
|
||||
import { Button, SaleDetailsPanel, PageLayout } from '../../components';
|
||||
import { getEntities } from '../../ducks/sdk.duck';
|
||||
import { loadData } from './SalePage.duck';
|
||||
import { acceptSale, loadData } from './SalePage.duck';
|
||||
|
||||
import css from './SalePage.css';
|
||||
|
||||
// SalePage handles data loading
|
||||
// It show loading data text or SaleDetailsPanel (and later also another panel for messages).
|
||||
export const SalePageComponent = props => {
|
||||
const { intl, transaction } = props;
|
||||
const { intl, onAcceptSale, transaction } = props;
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const currentListing = ensureListing(currentTransaction.listing);
|
||||
const title = currentListing.attributes.title;
|
||||
|
|
@ -22,6 +22,7 @@ export const SalePageComponent = props => {
|
|||
subtotalPrice: currentTransaction.attributes.total,
|
||||
commission: currentTransaction.attributes.commission,
|
||||
saleState: currentTransaction.attributes.state,
|
||||
lastTransitionedAt: currentTransaction.attributes.lastTransitionedAt,
|
||||
listing: currentListing,
|
||||
booking: ensureBooking(currentTransaction.booking),
|
||||
customer: ensureUser(currentTransaction.customer),
|
||||
|
|
@ -35,19 +36,29 @@ export const SalePageComponent = props => {
|
|||
? <SaleDetailsPanel className={detailsClassName} {...detailsProps} />
|
||||
: <h1 className={css.title}><FormattedMessage id="SalePage.loadingData" /></h1>;
|
||||
|
||||
const actionButtons = currentTransaction.attributes.state === propTypes.TX_STATE_PREAUTHORIZED
|
||||
? <div className={css.actionButtons}>
|
||||
<Button onClick={() => onAcceptSale(currentTransaction.id)}>
|
||||
<FormattedMessage id="SalePage.acceptButton" />
|
||||
</Button>
|
||||
</div>
|
||||
: null;
|
||||
|
||||
return (
|
||||
<PageLayout title={intl.formatMessage({ id: 'SalePage.title' }, { title })}>
|
||||
{panel}
|
||||
{actionButtons}
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
SalePageComponent.defaultProps = { transaction: null };
|
||||
|
||||
const { oneOf } = PropTypes;
|
||||
const { func, oneOf } = PropTypes;
|
||||
|
||||
SalePageComponent.propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
onAcceptSale: func.isRequired,
|
||||
tab: oneOf(['details', 'discussion']).isRequired,
|
||||
transaction: propTypes.transaction,
|
||||
};
|
||||
|
|
@ -63,7 +74,13 @@ const mapStateToProps = state => {
|
|||
};
|
||||
};
|
||||
|
||||
const SalePage = connect(mapStateToProps)(injectIntl(SalePageComponent));
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
onAcceptSale: transactionId => dispatch(acceptSale(transactionId)),
|
||||
};
|
||||
};
|
||||
|
||||
const SalePage = connect(mapStateToProps, mapDispatchToProps)(injectIntl(SalePageComponent));
|
||||
|
||||
SalePage.loadData = params => {
|
||||
return loadData(params);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ describe('SalePage', () => {
|
|||
});
|
||||
|
||||
const props = {
|
||||
onAcceptSale: () => {},
|
||||
transaction,
|
||||
tab: 'details',
|
||||
intl: fakeIntl,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ exports[`SalePage matches snapshot 1`] = `
|
|||
"type": "user",
|
||||
}
|
||||
}
|
||||
lastTransitionedAt={2017-06-01T00:00:00.000Z}
|
||||
listing={
|
||||
Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -65,5 +66,14 @@ exports[`SalePage matches snapshot 1`] = `
|
|||
"currency": "USD",
|
||||
}
|
||||
} />
|
||||
<div>
|
||||
<Button
|
||||
className={null}
|
||||
onClick={[Function]}>
|
||||
<FormattedMessage
|
||||
id="SalePage.acceptButton"
|
||||
values={Object {}} />
|
||||
</Button>
|
||||
</div>
|
||||
</Connect(withRouter(PageLayout))>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
"BookingDatesForm.youWontBeChargedInfo": "You won't be charged yet",
|
||||
"BookingInfo.bookingPeriod": "{bookingStart} - {bookingEnd}",
|
||||
"BookingInfo.bookingPeriodLabel": "Booking period:",
|
||||
"BookingInfo.commission": "Charged commission:",
|
||||
"BookingInfo.commission": "{marketplace} fee:",
|
||||
"BookingInfo.nightCount": "{count, number} {count, plural, one {night} other {nights}}",
|
||||
"BookingInfo.pricePerDay":"Price per night:",
|
||||
"BookingInfo.subtotal": "Subtotal:",
|
||||
|
|
@ -56,16 +56,21 @@
|
|||
"ListingPage.loadingListingData": "Loading listing data",
|
||||
"ListingPage.noListingData": "Could not find listing data",
|
||||
"ModalInMobile.closeModal": "Close modal",
|
||||
"OrderDetailsPanel.listingTitle": "You have requested to book {title}.",
|
||||
"OrderDetailsPanel.orderStatusMessage": "{providerName} has been notified about the booking request, so sit back and relax.",
|
||||
"OrderDetailsPanel.orderAcceptedTitle": "You have booked {title}.",
|
||||
"OrderDetailsPanel.orderRequestedTitle": "You have requested to book {title}.",
|
||||
"OrderDetailsPanel.orderAcceptedStatus": "{providerName} accepted the booking.",
|
||||
"OrderDetailsPanel.orderRequestedStatus": "{providerName} has been notified about the booking request, so sit back and relax.",
|
||||
"OrderPage.loadingData": "Loading order data.",
|
||||
"OrderPage.title": "Order details for ${title}.",
|
||||
"PageLayout.authInfoFailed": "Could not get authentication information.",
|
||||
"PageLayout.logoutFailed": "Logout failed. Please try again.",
|
||||
"PaginationLinks.previous": "Previous page",
|
||||
"PaginationLinks.next": "Next page",
|
||||
"SaleDetailsPanel.listingTitle": "{customerName} has requested to book {title}.",
|
||||
"SaleDetailsPanel.saleStatusMessage": "{customerName} is waiting for your response.",
|
||||
"SaleDetailsPanel.listingAcceptedTitle": "{customerName} has booked {title}.",
|
||||
"SaleDetailsPanel.listingRequestedTitle": "{customerName} has requested to book {title}.",
|
||||
"SaleDetailsPanel.saleAcceptedStatus": "You accepted the booking.",
|
||||
"SaleDetailsPanel.saleRequestedStatus": "{customerName} is waiting for your response.",
|
||||
"SalePage.acceptButton": "Accept",
|
||||
"SalePage.loadingData": "Loading sale data.",
|
||||
"SalePage.title": "Sale details for ${title}.",
|
||||
"SearchPage.foundResults": "{count, number} {count, plural, one {listing} other {listings}} found.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue