From 6d6ebbffc1a927dcc47ac205dba5db764bf146c1 Mon Sep 17 00:00:00 2001 From: Jenni Nurmi Date: Wed, 23 Jan 2019 13:27:22 +0200 Subject: [PATCH] Refactor InboxPage: use txHasBeenDelivered function, rename css classes, add txIsRequested check and handle unknown transition separately, filter unknown transitions when fetching data, don't render InboxItem if latest transition is unknown, update InboxPage tests. --- src/containers/InboxPage/InboxPage.css | 68 +++----- src/containers/InboxPage/InboxPage.duck.js | 2 + src/containers/InboxPage/InboxPage.js | 151 ++++++++++-------- src/containers/InboxPage/InboxPage.test.js | 8 +- .../__snapshots__/InboxPage.test.js.snap | 36 +++++ 5 files changed, 151 insertions(+), 114 deletions(-) diff --git a/src/containers/InboxPage/InboxPage.css b/src/containers/InboxPage/InboxPage.css index 058f0e19..6110de9b 100644 --- a/src/containers/InboxPage/InboxPage.css +++ b/src/containers/InboxPage/InboxPage.css @@ -331,8 +331,25 @@ /* Transaction status affects to certain font colors and weights */ -.nameEnquired, -.namePending { +.stateName { + /* This class is empty on purpose, it is used below for banned users */ +} + +.stateActionNeeded { + font-weight: var(--fontWeightSemiBold); + color: var(--attentionColor); +} + +.stateNoActionNeeded { + color: var(--matterColorAnti); +} + +.stateSucces { + font-weight: var(--fontWeightSemiBold); + color: var(--successColor); +} + +.nameEmphasized { font-weight: var(--fontWeightBold); /* baseline alignment fixes */ @@ -340,39 +357,11 @@ margin-bottom: 1px; } -.stateName { - /* This class is empty on purpose, it is used below for banned users */ -} - -.stateEnquired, -.stateRequested, -.statePending { - font-weight: var(--fontWeightSemiBold); - color: var(--attentionColor); -} - -.stateAccepted { - font-weight: var(--fontWeightSemiBold); - color: var(--successColor); -} - -.stateCanceled, -.stateDeclined, -.stateDelivered { - color: var(--matterColorAnti); -} - -.nameEnquiredOrder, -.nameRequested, -.nameDeclined, -.nameCanceled, -.nameAccepted, -.nameDelivered { +.nameNotEmphasized { font-weight: var(--fontWeightMedium); } -.bookingEnquired, -.bookingPending { +.bookingActionNeeded { color: var(--matterColor); margin-top: 4px; @@ -381,25 +370,16 @@ } } -.bookingRequested, -.bookingCanceled, -.bookingDeclined, -.bookingAccepted, -.bookingDelivered { +.bookingNoActionNeeded { color: var(--matterColorAnti); } -.lastTransitionedAtEnquired, -.lastTransitionedAtPending, -.lastTransitionedAtRequested { +.lastTransitionedAtEmphasized { color: var(--matterColor); font-weight: var(--fontWeightMedium); } -.lastTransitionedAtCanceled, -.lastTransitionedAtAccepted, -.lastTransitionedAtDeclined, -.lastTransitionedAtDelivered { +.lastTransitionedAtNotEmphasized { color: var(--matterColorAnti); } diff --git a/src/containers/InboxPage/InboxPage.duck.js b/src/containers/InboxPage/InboxPage.duck.js index 0276ec45..3e94cedc 100644 --- a/src/containers/InboxPage/InboxPage.duck.js +++ b/src/containers/InboxPage/InboxPage.duck.js @@ -2,6 +2,7 @@ import reverse from 'lodash/reverse'; import sortBy from 'lodash/sortBy'; import { storableError } from '../../util/errors'; import { parse } from '../../util/urlHelpers'; +import { TRANSITIONS } from '../../util/transaction'; import { addMarketplaceEntities } from '../../ducks/marketplaceData.duck'; const sortedTransactions = txs => @@ -91,6 +92,7 @@ export const loadData = (params, search) => (dispatch, getState, sdk) => { const apiQueryParams = { only: onlyFilter, + lastTransitions: TRANSITIONS, include: ['provider', 'provider.profileImage', 'customer', 'customer.profileImage', 'booking'], 'fields.image': ['variants.square-small', 'variants.square-small2x'], page, diff --git a/src/containers/InboxPage/InboxPage.js b/src/containers/InboxPage/InboxPage.js index fdf12722..f0e95c16 100644 --- a/src/containers/InboxPage/InboxPage.js +++ b/src/containers/InboxPage/InboxPage.js @@ -6,14 +6,12 @@ import { FormattedMessage, injectIntl, intlShape } from 'react-intl'; import moment from 'moment'; import classNames from 'classnames'; import { - txHasFirstReview, txIsAccepted, txIsCanceled, - txIsCompleted, txIsDeclinedOrExpired, txIsEnquired, txIsRequested, - txIsReviewed, + txHasBeenDelivered, } from '../../util/transaction'; import { LINE_ITEM_DAY, LINE_ITEM_UNITS, propTypes } from '../../util/types'; import { formatMoney } from '../../util/currency'; @@ -55,73 +53,85 @@ const formatDate = (intl, date) => { }; // Translated name of the state of the given transaction -const txState = (intl, tx, isOrder) => { - if (txIsAccepted(tx)) { +export const txState = (intl, tx, type) => { + const isOrder = type === 'order'; + + if (txIsEnquired(tx)) { return { - nameClassName: css.nameAccepted, - bookingClassName: css.bookingAccepted, - lastTransitionedAtClassName: css.lastTransitionedAtAccepted, - stateClassName: css.stateAccepted, - state: intl.formatMessage({ - id: 'InboxPage.stateAccepted', - }), - }; - } else if (txIsDeclinedOrExpired(tx)) { - return { - nameClassName: css.nameDeclined, - bookingClassName: css.bookingDeclined, - lastTransitionedAtClassName: css.lastTransitionedAtDeclined, - stateClassName: css.stateDeclined, - state: intl.formatMessage({ - id: 'InboxPage.stateDeclined', - }), - }; - } else if (txIsCanceled(tx)) { - return { - nameClassName: css.nameCanceled, - bookingClassName: css.bookingCanceled, - lastTransitionedAtClassName: css.lastTransitionedAtCanceled, - stateClassName: css.stateCanceled, - state: intl.formatMessage({ - id: 'InboxPage.stateCanceled', - }), - }; - } else if (txIsCompleted(tx) || txHasFirstReview(tx) || txIsReviewed(tx)) { - return { - nameClassName: css.nameDelivered, - bookingClassName: css.bookingDelivered, - lastTransitionedAtClassName: css.lastTransitionedAtDelivered, - stateClassName: css.stateDelivered, - state: intl.formatMessage({ - id: 'InboxPage.stateDelivered', - }), - }; - } else if (txIsEnquired(tx)) { - return { - nameClassName: isOrder ? css.nameEnquiredOrder : css.nameEnquired, - bookingClassName: css.bookingEnquired, - lastTransitionedAtClassName: css.lastTransitionedAtEnquired, - stateClassName: css.stateEnquired, + nameClassName: isOrder ? css.nameNotEmphasized : css.nameEmphasized, + bookingClassName: css.bookingActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtEmphasized, + stateClassName: css.stateActionNeeded, state: intl.formatMessage({ id: 'InboxPage.stateEnquiry', }), }; + } else if (txIsRequested(tx)) { + const requested = isOrder + ? { + nameClassName: css.nameNotEmphasized, + bookingClassName: css.bookingNoActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtEmphasized, + stateClassName: css.stateActionNeeded, + state: intl.formatMessage({ + id: 'InboxPage.stateRequested', + }), + } + : { + nameClassName: css.nameEmphasized, + bookingClassName: css.bookingActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtEmphasized, + stateClassName: css.stateActionNeeded, + state: intl.formatMessage({ + id: 'InboxPage.statePending', + }), + }; + + return requested; + } else if (txIsDeclinedOrExpired(tx)) { + return { + nameClassName: css.nameNotEmphasized, + bookingClassName: css.bookingNoActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtNotEmphasized, + stateClassName: css.stateNoActionNeeded, + state: intl.formatMessage({ + id: 'InboxPage.stateDeclined', + }), + }; + } else if (txIsAccepted(tx)) { + return { + nameClassName: css.nameNotEmphasized, + bookingClassName: css.bookingNoActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtNotEmphasized, + stateClassName: css.stateSucces, + state: intl.formatMessage({ + id: 'InboxPage.stateAccepted', + }), + }; + } else if (txIsCanceled(tx)) { + return { + nameClassName: css.nameNotEmphasized, + bookingClassName: css.bookingNoActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtNotEmphasized, + stateClassName: css.stateNoActionNeeded, + state: intl.formatMessage({ + id: 'InboxPage.stateCanceled', + }), + }; + } else if (txHasBeenDelivered(tx)) { + return { + nameClassName: css.nameNotEmphasized, + bookingClassName: css.bookingNoActionNeeded, + lastTransitionedAtClassName: css.lastTransitionedAtNotEmphasized, + stateClassName: css.stateNoActionNeeded, + state: intl.formatMessage({ + id: 'InboxPage.stateDelivered', + }), + }; + } else { + console.warn('This transition is unknown:', tx.attributes.lastTransition); + return null; } - return { - nameClassName: isOrder ? css.nameRequested : css.namePending, - bookingClassName: isOrder ? css.bookingRequested : css.bookingPending, - lastTransitionedAtClassName: isOrder - ? css.lastTransitionedAtRequested - : css.lastTransitionedAtPending, - stateClassName: isOrder ? css.stateRequested : css.statePending, - state: isOrder - ? intl.formatMessage({ - id: 'InboxPage.stateRequested', - }) - : intl.formatMessage({ - id: 'InboxPage.statePending', - }), - }; }; const bookingData = (unitType, tx, isOrder, intl) => { @@ -174,7 +184,7 @@ BookingInfoMaybe.propTypes = { }; export const InboxItem = props => { - const { unitType, type, tx, intl } = props; + const { unitType, type, tx, intl, stateData } = props; const { customer, provider } = tx; const isOrder = type === 'order'; @@ -185,7 +195,6 @@ export const InboxItem = props => { const isOtherUserBanned = otherUser.attributes.banned; const otherUserDisplayName = userDisplayName(otherUser, bannedUserDisplayName); - const stateData = txState(intl, tx, isOrder); const isSaleNotification = !isOrder && txIsRequested(tx); const rowNotificationDot = isSaleNotification ?
: null; const lastTransitionedAt = formatDate(intl, tx.attributes.lastTransitionedAt); @@ -268,11 +277,15 @@ export const InboxPageComponent = props => { const title = isOrders ? ordersTitle : salesTitle; const toTxItem = tx => { - return ( + const type = isOrders ? 'order' : 'sale'; + const stateData = txState(intl, tx, type); + + // Render InboxItem only if the latest transition of the transaction is handled in the `txState` function. + return stateData ? (
  • - +
  • - ); + ) : null; }; const error = fetchOrdersOrSalesError ? ( diff --git a/src/containers/InboxPage/InboxPage.test.js b/src/containers/InboxPage/InboxPage.test.js index 4bf71a01..f3eef444 100644 --- a/src/containers/InboxPage/InboxPage.test.js +++ b/src/containers/InboxPage/InboxPage.test.js @@ -8,7 +8,7 @@ import { createTransaction, createBooking, } from '../../util/test-data'; -import { InboxPageComponent, InboxItem } from './InboxPage'; +import { InboxPageComponent, InboxItem, txState } from './InboxPage'; import routeConfiguration from '../../routeConfiguration'; import { TRANSITION_REQUEST } from '../../util/transaction'; import { LINE_ITEM_NIGHT } from '../../util/types'; @@ -74,6 +74,8 @@ describe('InboxPage', () => { const ordersTree = renderShallow(); expect(ordersTree).toMatchSnapshot(); + const stateDataOrder = txState(fakeIntl, ordersProps.transactions[0], 'order'); + // Deeply render one InboxItem const orderItem = renderDeep( { type="order" tx={ordersProps.transactions[0]} intl={fakeIntl} + stateData={stateDataOrder} /> ); expect(orderItem).toMatchSnapshot(); @@ -128,6 +131,8 @@ describe('InboxPage', () => { const salesTree = renderShallow(); expect(salesTree).toMatchSnapshot(); + const stateDataSale = txState(fakeIntl, salesProps.transactions[0], 'sale'); + // Deeply render one InboxItem const saleItem = renderDeep( { type="sale" tx={salesProps.transactions[0]} intl={fakeIntl} + stateData={stateDataSale} /> ); expect(saleItem).toMatchSnapshot(); diff --git a/src/containers/InboxPage/__snapshots__/InboxPage.test.js.snap b/src/containers/InboxPage/__snapshots__/InboxPage.test.js.snap index 914c89a7..c1b3ae9c 100644 --- a/src/containers/InboxPage/__snapshots__/InboxPage.test.js.snap +++ b/src/containers/InboxPage/__snapshots__/InboxPage.test.js.snap @@ -91,6 +91,15 @@ exports[`InboxPage matches snapshot 1`] = ` "now": [Function], } } + stateData={ + Object { + "bookingClassName": undefined, + "lastTransitionedAtClassName": undefined, + "nameClassName": undefined, + "state": "InboxPage.stateRequested", + "stateClassName": undefined, + } + } tx={ Object { "attributes": Object { @@ -216,6 +225,15 @@ exports[`InboxPage matches snapshot 1`] = ` "now": [Function], } } + stateData={ + Object { + "bookingClassName": undefined, + "lastTransitionedAtClassName": undefined, + "nameClassName": undefined, + "state": "InboxPage.stateRequested", + "stateClassName": undefined, + } + } tx={ Object { "attributes": Object { @@ -483,6 +501,15 @@ exports[`InboxPage matches snapshot 3`] = ` "now": [Function], } } + stateData={ + Object { + "bookingClassName": undefined, + "lastTransitionedAtClassName": undefined, + "nameClassName": undefined, + "state": "InboxPage.statePending", + "stateClassName": undefined, + } + } tx={ Object { "attributes": Object { @@ -608,6 +635,15 @@ exports[`InboxPage matches snapshot 3`] = ` "now": [Function], } } + stateData={ + Object { + "bookingClassName": undefined, + "lastTransitionedAtClassName": undefined, + "nameClassName": undefined, + "state": "InboxPage.statePending", + "stateClassName": undefined, + } + } tx={ Object { "attributes": Object {