mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-27 19:42:11 +10:00
Merge pull request #549 from sharetribe/tx-transitions
Add transaction transitions to the order/sale pages
This commit is contained in:
commit
b035784e8d
15 changed files with 1458 additions and 68 deletions
|
|
@ -22,6 +22,13 @@ const exampleTransaction = params => {
|
|||
createdAt: created,
|
||||
lastTransitionedAt: created,
|
||||
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
transitions: [
|
||||
{
|
||||
at: created,
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
},
|
||||
],
|
||||
|
||||
// payinTotal, payoutTotal, and lineItems required in params
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,13 @@ const exampleTransaction = params => {
|
|||
createdAt: created,
|
||||
lastTransitionedAt: created,
|
||||
lastTransition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
transitions: [
|
||||
{
|
||||
at: created,
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
},
|
||||
],
|
||||
|
||||
// payinTotal, payoutTotal, and lineItems required in params
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
}
|
||||
|
||||
.messageItem {
|
||||
margin-bottom: 35px;
|
||||
margin-bottom: 38px;
|
||||
|
||||
/* Clearfix */
|
||||
@apply --clearfix;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 41px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
|
|
@ -41,7 +41,11 @@
|
|||
|
||||
.avatar {
|
||||
flex-shrink: 0;
|
||||
margin: 9px 12px 0 0;
|
||||
margin: 6px 12px 0 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: 9px 12px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.messageContent,
|
||||
|
|
@ -49,11 +53,12 @@
|
|||
@apply --marketplaceMessageFontStyles;
|
||||
|
||||
margin: 0;
|
||||
padding: 15px 14px 11px 14px;
|
||||
padding: 12px 14px 11px 14px;
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--boxShadow);
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: 14px 14px 11px 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -81,3 +86,47 @@
|
|||
.ownMessageDate {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.transitionItem {
|
||||
margin-bottom: 36px;
|
||||
|
||||
/* Clearfix */
|
||||
@apply --clearfix;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.transition {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 3px 0 2px 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.transitionContent {
|
||||
@apply --marketplaceTxTransitionFontStyles;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.transitionDate {
|
||||
@apply --marketplaceMessageDateFontStyles;
|
||||
color: var(--matterColorAnti);
|
||||
margin: 7px 0 0 0;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
margin: -1px 0 1px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.bullet {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,12 @@
|
|||
import { createUser, createCurrentUser, createMessage } from '../../util/test-data';
|
||||
import {
|
||||
createUser,
|
||||
createCurrentUser,
|
||||
createMessage,
|
||||
createTransaction,
|
||||
createListing,
|
||||
createTxTransition,
|
||||
} from '../../util/test-data';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import Messages from './Messages';
|
||||
|
||||
export const Empty = {
|
||||
|
|
@ -6,6 +14,9 @@ export const Empty = {
|
|||
props: {
|
||||
messages: [],
|
||||
currentUser: null,
|
||||
transaction: null,
|
||||
customer: null,
|
||||
provider: null,
|
||||
},
|
||||
group: 'messages',
|
||||
};
|
||||
|
|
@ -34,3 +45,86 @@ export const WithCurrentUser = {
|
|||
},
|
||||
group: 'messages',
|
||||
};
|
||||
|
||||
export const WithTransitions = {
|
||||
component: Messages,
|
||||
props: {
|
||||
messages: [],
|
||||
transaction: createTransaction({
|
||||
customer: createUser('user1'),
|
||||
provider: createUser('user2'),
|
||||
listing: createListing('Listing'),
|
||||
transitions: [
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 8, 10)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
}),
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 8, 12)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_PROVIDER,
|
||||
transition: propTypes.TX_TRANSITION_ACCEPT,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
currentUser: createCurrentUser('user2'),
|
||||
},
|
||||
group: 'messages',
|
||||
};
|
||||
|
||||
export const WithMessagesAndTransitions = {
|
||||
component: Messages,
|
||||
props: {
|
||||
messages: [
|
||||
createMessage(
|
||||
'msg1',
|
||||
{ at: new Date(Date.UTC(2017, 10, 9, 8, 11)) },
|
||||
{ sender: createUser('user1') }
|
||||
),
|
||||
createMessage(
|
||||
'msg2',
|
||||
{ at: new Date(Date.UTC(2017, 10, 9, 8, 14)) },
|
||||
{ sender: createUser('user1') }
|
||||
),
|
||||
createMessage(
|
||||
'msg3',
|
||||
{ at: new Date(Date.UTC(2017, 10, 9, 8, 17)) },
|
||||
{ sender: createUser('user2') }
|
||||
),
|
||||
createMessage(
|
||||
'msg4',
|
||||
{ at: new Date(Date.UTC(2017, 10, 12, 13, 20)) },
|
||||
{ sender: createUser('user2') }
|
||||
),
|
||||
],
|
||||
transaction: createTransaction({
|
||||
customer: createUser('user1'),
|
||||
provider: createUser('user2'),
|
||||
listing: createListing('Listing'),
|
||||
transitions: [
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 8, 10)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
}),
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 8, 12)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_PROVIDER,
|
||||
transition: propTypes.TX_TRANSITION_ACCEPT,
|
||||
}),
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 10, 33)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_PROVIDER,
|
||||
transition: propTypes.TX_TRANSITION_DECLINE,
|
||||
}),
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 10, 9, 10, 34)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_PROVIDER,
|
||||
transition: propTypes.TX_TRANSITION_MARK_DELIVERED,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
currentUser: createCurrentUser('user2'),
|
||||
},
|
||||
group: 'messages',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { injectIntl, intlShape } from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
import { Avatar } from '../../components';
|
||||
import { formatDate } from '../../util/dates';
|
||||
import { ensureTransaction, ensureUser } from '../../util/data';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
|
||||
import css from './Messages.css';
|
||||
|
|
@ -43,11 +44,133 @@ OwnMessage.propTypes = {
|
|||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const Transition = props => {
|
||||
const { transition, currentUser, customer, provider, listingTitle, intl } = props;
|
||||
|
||||
const resolveTransitionMessage = (transition, ownRole, otherUsersName, intl) => {
|
||||
const isOwnTransition = transition.by === ownRole;
|
||||
const transitionType = transition.transition;
|
||||
const displayName = otherUsersName;
|
||||
|
||||
switch (transitionType) {
|
||||
case propTypes.TX_TRANSITION_PREAUTHORIZE:
|
||||
return isOwnTransition
|
||||
? intl.formatMessage({ id: 'Messages.ownTransitionRequest' }, { listingTitle })
|
||||
: intl.formatMessage({ id: 'Messages.transitionRequest' }, { displayName, listingTitle });
|
||||
case propTypes.TX_TRANSITION_ACCEPT:
|
||||
return isOwnTransition
|
||||
? intl.formatMessage({ id: 'Messages.ownTransitionAccept' })
|
||||
: intl.formatMessage({ id: 'Messages.transitionAccept' }, { displayName });
|
||||
case propTypes.TX_TRANSITION_DECLINE:
|
||||
return isOwnTransition
|
||||
? intl.formatMessage({ id: 'Messages.ownTransitionDecline' })
|
||||
: intl.formatMessage({ id: 'Messages.transitionDecline' }, { displayName });
|
||||
case propTypes.TX_TRANSITION_AUTO_DECLINE:
|
||||
return ownRole === propTypes.TX_TRANSITION_ACTOR_PROVIDER
|
||||
? intl.formatMessage({ id: 'Messages.ownTransitionAutoDecline' })
|
||||
: intl.formatMessage({ id: 'Messages.transitionAutoDecline' }, { displayName });
|
||||
case propTypes.TX_TRANSITION_MARK_DELIVERED:
|
||||
return intl.formatMessage({ id: 'Messages.transitionComplete' });
|
||||
case propTypes.TX_TRANSITION_CANCEL:
|
||||
return intl.formatMessage({ id: 'Messages.transitionCancel' });
|
||||
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
const ownRole =
|
||||
currentUser.id.uuid === customer.id.uuid
|
||||
? propTypes.TX_TRANSITION_ACTOR_CUSTOMER
|
||||
: propTypes.TX_TRANSITION_ACTOR_PROVIDER;
|
||||
|
||||
const otherUsersName =
|
||||
ownRole === propTypes.TX_TRANSITION_ACTOR_CUSTOMER
|
||||
? provider.attributes.profile.displayName
|
||||
: customer.attributes.profile.displayName;
|
||||
|
||||
const transitionMessage = resolveTransitionMessage(transition, ownRole, otherUsersName, intl);
|
||||
const todayString = intl.formatMessage({ id: 'Messages.today' });
|
||||
|
||||
return (
|
||||
<div className={css.transition}>
|
||||
<div className={css.bullet}>
|
||||
<p className={css.transitionContent}>•</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className={css.transitionContent}>{transitionMessage}</p>
|
||||
<p className={css.transitionDate}>{formatDate(intl, todayString, transition.at)}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Transition.propTypes = {
|
||||
transition: propTypes.txTransition.isRequired,
|
||||
currentUser: propTypes.currentUser.isRequired,
|
||||
customer: propTypes.user.isRequired,
|
||||
provider: propTypes.user.isRequired,
|
||||
listingTitle: string.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
const EmptyTransition = () => {
|
||||
return (
|
||||
<div className={css.transition}>
|
||||
<div className={css.bullet}>
|
||||
<p className={css.transitionContent}>•</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className={css.transitionContent} />
|
||||
<p className={css.transitionDate} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const MessagesComponent = props => {
|
||||
const { rootClassName, className, messages, currentUser, intl } = props;
|
||||
const { rootClassName, className, messages, transaction, currentUser, intl } = props;
|
||||
const classes = classNames(rootClassName || css.root, className);
|
||||
|
||||
const msg = message => {
|
||||
const currentTransaction = ensureTransaction(transaction);
|
||||
const transitions = currentTransaction.attributes.transitions
|
||||
? currentTransaction.attributes.transitions
|
||||
: [];
|
||||
const currentCustomer = ensureUser(currentTransaction.customer);
|
||||
const currentProvider = ensureUser(currentTransaction.provider);
|
||||
|
||||
const transitionsAvailable =
|
||||
currentUser && currentUser.id && currentCustomer.id && currentProvider.id;
|
||||
|
||||
const isMessage = item => item && item.type === 'message';
|
||||
|
||||
// Compare function for sorting an array containint messages and transitions
|
||||
const compareItems = (a, b) => {
|
||||
const itemDate = item => (isMessage(item) ? item.attributes.at : item.at);
|
||||
return itemDate(a) - itemDate(b);
|
||||
};
|
||||
|
||||
// combine messages and transaction transitions
|
||||
const items = messages.concat(transitions).sort(compareItems);
|
||||
|
||||
const transitionComponent = transition => {
|
||||
if (transitionsAvailable) {
|
||||
return (
|
||||
<Transition
|
||||
transition={transition}
|
||||
currentUser={currentUser}
|
||||
customer={currentCustomer}
|
||||
provider={currentProvider}
|
||||
listingTitle={currentTransaction.listing.attributes.title}
|
||||
intl={intl}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return <EmptyTransition />;
|
||||
}
|
||||
};
|
||||
|
||||
const messageComponent = message => {
|
||||
const isOwnMessage =
|
||||
message.sender &&
|
||||
message.sender.id &&
|
||||
|
|
@ -60,13 +183,31 @@ export const MessagesComponent = props => {
|
|||
return <Message message={message} intl={intl} />;
|
||||
};
|
||||
|
||||
const messageListItem = message => {
|
||||
return (
|
||||
<li id={`msg-${message.id.uuid}`} key={message.id.uuid} className={css.messageItem}>
|
||||
{messageComponent(message)}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const transitionListItem = transition => {
|
||||
return (
|
||||
<li key={transition.transition} className={css.transitionItem}>
|
||||
{transitionComponent(transition)}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className={classes}>
|
||||
{messages.map(m => (
|
||||
<li id={`msg-${m.id.uuid}`} key={m.id.uuid} className={css.messageItem}>
|
||||
{msg(m)}
|
||||
</li>
|
||||
))}
|
||||
{items.map(item => {
|
||||
if (isMessage(item)) {
|
||||
return messageListItem(item);
|
||||
} else {
|
||||
return transitionListItem(item);
|
||||
}
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
|
@ -81,6 +222,7 @@ MessagesComponent.propTypes = {
|
|||
className: string,
|
||||
|
||||
messages: arrayOf(propTypes.message),
|
||||
transaction: propTypes.transaction,
|
||||
currentUser: propTypes.currentUser,
|
||||
|
||||
// from injectIntl
|
||||
|
|
|
|||
|
|
@ -155,7 +155,11 @@ export class OrderDetailsPanelComponent extends Component {
|
|||
const messagesContainerClasses = classNames(css.messagesContainer, {
|
||||
[css.messagesContainerWithInfoAbove]: showInfoMessage,
|
||||
});
|
||||
const showMessages = messages.length > 0 || initialMessageFailed || fetchMessagesError;
|
||||
const txTransitions = currentTransaction.attributes.transitions
|
||||
? currentTransaction.attributes.transitions
|
||||
: [];
|
||||
const showMessages =
|
||||
messages.length > 0 || txTransitions.length > 0 || initialMessageFailed || fetchMessagesError;
|
||||
const messagesContainer = showMessages ? (
|
||||
<div className={messagesContainerClasses}>
|
||||
<h3 className={css.messagesHeading}>
|
||||
|
|
@ -171,7 +175,12 @@ export class OrderDetailsPanelComponent extends Component {
|
|||
<FormattedMessage id="OrderDetailsPanel.messageLoadingFailed" />
|
||||
</p>
|
||||
) : null}
|
||||
<Messages className={css.messages} messages={messages} currentUser={currentUser} />
|
||||
<Messages
|
||||
className={css.messages}
|
||||
messages={messages}
|
||||
transaction={currentTransaction}
|
||||
currentUser={currentUser}
|
||||
/>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -151,6 +151,18 @@ exports[`SaleDetailsPanel accepted matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -379,6 +391,18 @@ exports[`SaleDetailsPanel accepted matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -590,6 +614,18 @@ exports[`SaleDetailsPanel autodeclined matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -818,6 +854,18 @@ exports[`SaleDetailsPanel autodeclined matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -948,7 +996,7 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
</div>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.listingRequestedTitle"
|
||||
id="SaleDetailsPanel.listingAcceptedTitle"
|
||||
values={
|
||||
Object {
|
||||
"customerName": "customer1 display name",
|
||||
|
|
@ -967,16 +1015,6 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
}
|
||||
/>
|
||||
</h1>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="SaleDetailsPanel.saleRequestedStatus"
|
||||
values={
|
||||
Object {
|
||||
"customerName": "customer1 display name",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<div />
|
||||
<div>
|
||||
<h3>
|
||||
|
|
@ -1002,7 +1040,7 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
Object {
|
||||
"attributes": Object {
|
||||
"createdAt": 2017-05-01T00:00:00.000Z,
|
||||
"lastTransition": "transition/preauthorize",
|
||||
"lastTransition": "transition/accept",
|
||||
"lastTransitionedAt": 2017-06-10T00:00:00.000Z,
|
||||
"lineItems": Array [
|
||||
Object {
|
||||
|
|
@ -1039,6 +1077,18 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -1095,7 +1145,7 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
className="undefined"
|
||||
className=""
|
||||
>
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
|
@ -1180,29 +1230,6 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div />
|
||||
<SecondaryButton
|
||||
disabled={false}
|
||||
inProgress={false}
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="SalePage.declineButton"
|
||||
values={Object {}}
|
||||
/>
|
||||
</SecondaryButton>
|
||||
<PrimaryButton
|
||||
disabled={false}
|
||||
inProgress={false}
|
||||
onClick={[Function]}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="SalePage.acceptButton"
|
||||
values={Object {}}
|
||||
/>
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
|
|
@ -1253,7 +1280,7 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
Object {
|
||||
"attributes": Object {
|
||||
"createdAt": 2017-05-01T00:00:00.000Z,
|
||||
"lastTransition": "transition/preauthorize",
|
||||
"lastTransition": "transition/accept",
|
||||
"lastTransitionedAt": 2017-06-10T00:00:00.000Z,
|
||||
"lineItems": Array [
|
||||
Object {
|
||||
|
|
@ -1290,6 +1317,18 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -1501,6 +1540,18 @@ exports[`SaleDetailsPanel declined matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -1729,6 +1780,18 @@ exports[`SaleDetailsPanel declined matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -1940,6 +2003,18 @@ exports[`SaleDetailsPanel delivered matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -2168,6 +2243,18 @@ exports[`SaleDetailsPanel delivered matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -2389,6 +2476,18 @@ exports[`SaleDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -2640,6 +2739,18 @@ exports[`SaleDetailsPanel preauthorized matches snapshot 1`] = `
|
|||
"amount": 15500,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -130,6 +130,18 @@ exports[`InboxPage matches snapshot 1`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -232,6 +244,18 @@ exports[`InboxPage matches snapshot 1`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -492,6 +516,18 @@ exports[`InboxPage matches snapshot 3`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
@ -594,6 +630,18 @@ exports[`InboxPage matches snapshot 3`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -89,6 +89,18 @@ exports[`OrderPage matches snapshot 1`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -95,6 +95,18 @@ exports[`SalePage matches snapshot 1`] = `
|
|||
"amount": 900,
|
||||
"currency": "USD",
|
||||
},
|
||||
"transitions": Array [
|
||||
Object {
|
||||
"at": 2017-05-01T00:00:00.000Z,
|
||||
"by": "customer",
|
||||
"transition": "transition/preauthorize",
|
||||
},
|
||||
Object {
|
||||
"at": 2017-06-01T00:00:00.000Z,
|
||||
"by": "provider",
|
||||
"transition": "transition/accept",
|
||||
},
|
||||
],
|
||||
},
|
||||
"booking": Object {
|
||||
"attributes": Object {
|
||||
|
|
|
|||
|
|
@ -231,6 +231,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
--marketplaceTxTransitionFontStyles {
|
||||
font-family: 'sofiapro', Helvetica, Arial, sans-serif;
|
||||
font-weight: var(--fontWeightMedium);
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
|
||||
@media (--viewportMedium) {
|
||||
font-size: 20px;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================ Tabbed navigation font styles ================ */
|
||||
|
||||
--marketplaceTabNavFontStyles {
|
||||
|
|
|
|||
|
|
@ -248,7 +248,17 @@
|
|||
"ManageListingsPage.youHaveListings": "You have {count} {count, plural, one {listing} other {listings}}",
|
||||
"ManageListingsPage.yourListings": "Your listings",
|
||||
"MapPriceMarker.unsupportedPrice": "({currency})",
|
||||
"Messages.ownTransitionAccept": "You accepted the booking request.",
|
||||
"Messages.ownTransitionAutoDecline": "Booking request expired. You did not reply in time.",
|
||||
"Messages.ownTransitionDecline": "You declined the booking request.",
|
||||
"Messages.ownTransitionRequest": "You requested to book { listingTitle }.",
|
||||
"Messages.today": "Today",
|
||||
"Messages.transitionAccept": "{ displayName } accepted the booking request.",
|
||||
"Messages.transitionAutoDecline": "Booking request expired. { displayName } did not reply in time.",
|
||||
"Messages.transitionComplete": "Booking was completed.",
|
||||
"Messages.transitionCancel": "Booking was cancelled.",
|
||||
"Messages.transitionDecline": "{ displayName } declined the booking request.",
|
||||
"Messages.transitionRequest": "{ displayName } requested to book { listingTitle }.",
|
||||
"Modal.close": "CLOSE",
|
||||
"Modal.closeModal": "Close modal",
|
||||
"NotFoundPage.description": "We can't find the page or the sauna you're looking for. Make sure you've typed the URL correctly, of try searching Saunatime.",
|
||||
|
|
|
|||
|
|
@ -172,6 +172,19 @@ export const TX_TRANSITIONS = [
|
|||
TX_TRANSITION_MARK_DELIVERED,
|
||||
];
|
||||
|
||||
// Roles of actors that perform transaction transitions
|
||||
export const TX_TRANSITION_ACTOR_CUSTOMER = 'customer';
|
||||
export const TX_TRANSITION_ACTOR_PROVIDER = 'provider';
|
||||
export const TX_TRANSITION_ACTOR_SYSTEM = 'system';
|
||||
export const TX_TRANSITION_ACTOR_OPERATOR = 'operator';
|
||||
|
||||
export const TX_TRANSITION_ACTORS = [
|
||||
TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
TX_TRANSITION_ACTOR_PROVIDER,
|
||||
TX_TRANSITION_ACTOR_SYSTEM,
|
||||
TX_TRANSITION_ACTOR_OPERATOR,
|
||||
];
|
||||
|
||||
const txLastTransition = tx => ensureTransaction(tx).attributes.lastTransition;
|
||||
|
||||
export const txIsPreauthorized = tx => txLastTransition(tx) === TX_TRANSITION_PREAUTHORIZE;
|
||||
|
|
@ -188,6 +201,12 @@ export const txIsCanceled = tx => txLastTransition(tx) === TX_TRANSITION_CANCEL;
|
|||
|
||||
export const txIsDelivered = tx => txLastTransition(tx) === TX_TRANSITION_MARK_DELIVERED;
|
||||
|
||||
export const txTransition = shape({
|
||||
at: instanceOf(Date).isRequired,
|
||||
by: oneOf(TX_TRANSITION_ACTORS).isRequired,
|
||||
transition: oneOf(TX_TRANSITIONS).isRequired,
|
||||
});
|
||||
|
||||
// Denormalised transaction object
|
||||
export const transaction = shape({
|
||||
id: uuid.isRequired,
|
||||
|
|
@ -207,6 +226,7 @@ export const transaction = shape({
|
|||
reversal: bool.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
transitions: arrayOf(txTransition).isRequired,
|
||||
}),
|
||||
booking,
|
||||
listing,
|
||||
|
|
|
|||
|
|
@ -86,10 +86,19 @@ export const createListing = (id, attributes = {}, includes = {}) => ({
|
|||
...includes,
|
||||
});
|
||||
|
||||
export const createTxTransition = options => {
|
||||
return {
|
||||
at: new Date(Date.UTC(2017, 4, 1)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
...options,
|
||||
};
|
||||
};
|
||||
|
||||
export const createTransaction = options => {
|
||||
const {
|
||||
id,
|
||||
lastTransition = propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
lastTransition = propTypes.TX_TRANSITION_ACCEPT,
|
||||
total = new Money(1000, 'USD'),
|
||||
commission = new Money(100, 'USD'),
|
||||
booking = null,
|
||||
|
|
@ -97,6 +106,18 @@ export const createTransaction = options => {
|
|||
customer = null,
|
||||
provider = null,
|
||||
lastTransitionedAt = new Date(Date.UTC(2017, 5, 1)),
|
||||
transitions = [
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 4, 1)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_CUSTOMER,
|
||||
transition: propTypes.TX_TRANSITION_PREAUTHORIZE,
|
||||
}),
|
||||
createTxTransition({
|
||||
at: new Date(Date.UTC(2017, 5, 1)),
|
||||
by: propTypes.TX_TRANSITION_ACTOR_PROVIDER,
|
||||
transition: propTypes.TX_TRANSITION_ACCEPT,
|
||||
}),
|
||||
],
|
||||
} = options;
|
||||
const nightCount = booking ? nightsBetween(booking.attributes.start, booking.attributes.end) : 1;
|
||||
return {
|
||||
|
|
@ -123,6 +144,7 @@ export const createTransaction = options => {
|
|||
reversal: false,
|
||||
},
|
||||
],
|
||||
transitions,
|
||||
},
|
||||
booking,
|
||||
listing,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue