Skip to content

Commit

Permalink
[Wallet]: Add Payments You've Requested notifications group & screen (#…
Browse files Browse the repository at this point in the history
…1902)

* Split Payment Requests into incoming and outgoing.
* Implement Cancel feature on an outgoing payment request.
* Implement Remind feature on an outgoing payment request.
* Fix old tests for incoming requests.
* Create new tests for outgoing requests.
* Refactor code duplication between incoming and outgoing requests.
* Add Spanish translations.
  • Loading branch information
i1skn authored and jmrossy committed Nov 29, 2019
1 parent 34a62de commit d2ec8e8
Show file tree
Hide file tree
Showing 43 changed files with 2,940 additions and 185 deletions.
3 changes: 3 additions & 0 deletions packages/mobile/locales/en-US/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
"invalidAccount": "Invalid Account",
"delete": "Delete",
"cancel": "Cancel",
"remind": "Remind",
"pay": "Pay",
"decline": "Decline",
"to": "To",
"for": "For",
"celoGold": "Celo Gold",
Expand Down
8 changes: 4 additions & 4 deletions packages/mobile/locales/en-US/paymentRequestFlow.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"requests": "Requests",
"empty": "You have no Payment Requests",
"paymentRequests": "Payment Requests",
"incomingPaymentRequests": "Requests Waiting for You",
"outgoingPaymentRequests": "Payments You’ve Requested",
"celoDollarBalance": "{{CeloDollar}} Balance",
"pay": "Pay",
"decline": "Decline",
"requestDeclined": "Request Declined",
"requestPaid": "Request Paid"
"requestPaid": "Request Paid",
"paymentRequestUpdateFailed": "Cannot update payment request"
}
6 changes: 4 additions & 2 deletions packages/mobile/locales/en-US/walletFlow5.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"getStarted": "Get Started",
"paymentRequest": "Payment Request",
"paymentRequestWithCount_plural": "{{count}} Payment Requests",
"incomingPaymentRequest": "Request Waiting for You",
"incomingPaymentRequestWithCount_plural": "{{count}} Requests Waiting on You",
"outgoingPaymentRequest": "Payment You’ve Requested",
"outgoingPaymentRequestWithCount_plural": "{{count}} Payments You’ve Requested",
"SMSError": "Error sending SMS",
"notifications": "Notifications",
"getBackupKey": "Get Backup Key",
Expand Down
3 changes: 3 additions & 0 deletions packages/mobile/locales/es-419/global.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@
"invalidAccount": "Cuenta inválida",
"delete": "Eliminar",
"cancel": "Cancelar",
"remind": "Recordar",
"pay": "Paga",
"decline": "Disminución",
"to": "Para",
"for": "Por",
"celoGold": "Celo Oro",
Expand Down
8 changes: 4 additions & 4 deletions packages/mobile/locales/es-419/paymentRequestFlow.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"requests": "Solicitudes",
"empty": "No tienes solicitudes de pago",
"paymentRequests": "Solicitudes de pago",
"incomingPaymentRequests": "Pedidos esperandote",
"outgoingPaymentRequests": "Pagos que tu has pedido",
"celoDollarBalance": "Saldo de {{CeloDollar}}",
"pay": "Paga",
"decline": "Disminución",
"requestDeclined": "Solicitud rechazada",
"requestPaid": "Solicitud Pagada"
"requestPaid": "Solicitud Pagada",
"paymentRequestUpdateFailed": "No se pudo actualizar el pedido de pago"
}
6 changes: 4 additions & 2 deletions packages/mobile/locales/es-419/walletFlow5.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"getStarted": "Primeros pasos",
"paymentRequest": "Solicitud de pago",
"paymentRequestWithCount_plural": "{{count}} solicitudes de pago",
"incomingPaymentRequest": "Pedido esperandote",
"incomingPaymentRequestWithCount_plural": "{{count}} Pedidos esperandote",
"outgoingPaymentRequest": "Pago que tu has pedido",
"outgoingPaymentRequestWithCount_plural": "{{count}} Pagos que tu has pedido",
"SMSError": "Error al enviar SMS",
"notifications": "Notificaciones",
"getBackupKey": "Obtener clave de respaldo",
Expand Down
28 changes: 21 additions & 7 deletions packages/mobile/src/account/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export enum Actions {
SET_BACKUP_DELAYED_ACTION = 'ACCOUNT/SET_BACKUP_DELAYED_ACTION',
SET_SOCIAL_BACKUP_COMPLETED_ACTION = 'ACCOUNT/SET_SOCIAL_BACKUP_COMPLETED_ACTION',
RESET_BACKUP_STATE = 'ACCOUNT/RESET_BACKUP_STATE',
UPDATE_PAYMENT_REQUESTS = 'ACCOUNT/UPDATE_PAYMENT_REQUESTS',
UPDATE_INCOMING_PAYMENT_REQUESTS = 'ACCOUNT/UPDATE_INCOMING_PAYMENT_REQUESTS',
UPDATE_OUTGOING_PAYMENT_REQUESTS = 'ACCOUNT/UPDATE_OUTGOING_PAYMENT_REQUESTS',
DISMISS_EARN_REWARDS = 'ACCOUNT/DISMISS_EARN_REWARDS',
DISMISS_INVITE_FRIENDS = 'ACCOUNT/DISMISS_INVITE_FRIENDS',
SET_USER_CONTACT_DETAILS = 'ACCOUNT/SET_USER_CONTACT_DETAILS',
Expand Down Expand Up @@ -77,8 +78,13 @@ export interface ResetBackupState {
type: Actions.RESET_BACKUP_STATE
}

export interface UpdatePaymentRequestsAction {
type: Actions.UPDATE_PAYMENT_REQUESTS
export interface UpdateIncomingPaymentRequestsAction {
type: Actions.UPDATE_INCOMING_PAYMENT_REQUESTS
paymentRequests: PaymentRequest[]
}

export interface UpdateOutgoingPaymentRequestsAction {
type: Actions.UPDATE_OUTGOING_PAYMENT_REQUESTS
paymentRequests: PaymentRequest[]
}

Expand Down Expand Up @@ -109,7 +115,8 @@ export type ActionTypes =
| SetBackupDelayedAction
| SetSocialBackupCompletedAction
| ResetBackupState
| UpdatePaymentRequestsAction
| UpdateIncomingPaymentRequestsAction
| UpdateOutgoingPaymentRequestsAction
| DismissEarnRewards
| DismissInviteFriends
| SetContactDetailsAction
Expand Down Expand Up @@ -173,10 +180,17 @@ export const resetBackupState = (): ResetBackupState => ({
type: Actions.RESET_BACKUP_STATE,
})

export const updatePaymentRequests = (
export const updateIncomingPaymentRequests = (
paymentRequests: PaymentRequest[]
): UpdateIncomingPaymentRequestsAction => ({
type: Actions.UPDATE_INCOMING_PAYMENT_REQUESTS,
paymentRequests,
})

export const updateOutgoingPaymentRequests = (
paymentRequests: PaymentRequest[]
): UpdatePaymentRequestsAction => ({
type: Actions.UPDATE_PAYMENT_REQUESTS,
): UpdateOutgoingPaymentRequestsAction => ({
type: Actions.UPDATE_OUTGOING_PAYMENT_REQUESTS,
paymentRequests,
})

Expand Down
15 changes: 11 additions & 4 deletions packages/mobile/src/account/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export interface State {
backupCompleted: boolean
backupDelayedTime: number
socialBackupCompleted: boolean
paymentRequests: PaymentRequest[]
incomingPaymentRequests: PaymentRequest[]
outgoingPaymentRequests: PaymentRequest[]
dismissedEarnRewards: boolean
dismissedInviteFriends: boolean
}
Expand Down Expand Up @@ -49,7 +50,8 @@ export const initialState = {
pincodeType: PincodeType.Unset,
isSettingPin: false,
accountCreationTime: 99999999999999,
paymentRequests: [],
incomingPaymentRequests: [],
outgoingPaymentRequests: [],
backupCompleted: false,
backupDelayedTime: 0,
socialBackupCompleted: false,
Expand Down Expand Up @@ -129,10 +131,15 @@ export const reducer = (state: State | undefined = initialState, action: ActionT
socialBackupCompleted: false,
backupDelayedTime: 0,
}
case Actions.UPDATE_PAYMENT_REQUESTS:
case Actions.UPDATE_INCOMING_PAYMENT_REQUESTS:
return {
...state,
paymentRequests: action.paymentRequests,
incomingPaymentRequests: action.paymentRequests,
}
case Actions.UPDATE_OUTGOING_PAYMENT_REQUESTS:
return {
...state,
outgoingPaymentRequests: action.paymentRequests,
}
case Actions.DISMISS_EARN_REWARDS:
return {
Expand Down
43 changes: 37 additions & 6 deletions packages/mobile/src/account/selectors.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { getPaymentRequests } from 'src/account/selectors'
import { getIncomingPaymentRequests, getOutgoingPaymentRequests } from 'src/account/selectors'
import { PaymentRequestStatus } from 'src/account/types'
import { paymentRequestDouble } from 'src/paymentRequest/__mocks__'

describe('selectors', () => {
describe(getPaymentRequests, () => {
describe(getIncomingPaymentRequests, () => {
it('excludes declined and completed requests', () => {
const state: any = {
account: {
paymentRequests: [
incomingPaymentRequests: [
paymentRequestDouble({ status: PaymentRequestStatus.DECLINED }),
paymentRequestDouble({ status: PaymentRequestStatus.COMPLETED }),
],
},
}
expect(getPaymentRequests(state)).toEqual([])
expect(getIncomingPaymentRequests(state)).toEqual([])
})

it('returns requested payments', () => {
const goodRequest = paymentRequestDouble({ status: PaymentRequestStatus.REQUESTED })

const state: any = {
account: {
paymentRequests: [
incomingPaymentRequests: [
paymentRequestDouble({
status: PaymentRequestStatus.COMPLETED,
}),
Expand All @@ -30,7 +30,38 @@ describe('selectors', () => {
},
}

expect(getPaymentRequests(state)).toEqual([goodRequest])
expect(getIncomingPaymentRequests(state)).toEqual([goodRequest])
})
})

describe(getOutgoingPaymentRequests, () => {
it('excludes declined and completed requests', () => {
const state: any = {
account: {
outgoingPaymentRequests: [
paymentRequestDouble({ status: PaymentRequestStatus.DECLINED }),
paymentRequestDouble({ status: PaymentRequestStatus.COMPLETED }),
],
},
}
expect(getOutgoingPaymentRequests(state)).toEqual([])
})

it('returns requested payments', () => {
const goodRequest = paymentRequestDouble({ status: PaymentRequestStatus.REQUESTED })

const state: any = {
account: {
outgoingPaymentRequests: [
paymentRequestDouble({
status: PaymentRequestStatus.COMPLETED,
}),
goodRequest,
],
},
}

expect(getOutgoingPaymentRequests(state)).toEqual([goodRequest])
})
})
})
10 changes: 8 additions & 2 deletions packages/mobile/src/account/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { PaymentRequestStatus } from 'src/account/types'
import { RootState } from 'src/redux/reducers'

export const getPaymentRequests = (state: RootState) => {
return (state.account.paymentRequests || []).filter(
export const getIncomingPaymentRequests = (state: RootState) => {
return (state.account.incomingPaymentRequests || []).filter(
(p) => p.status === PaymentRequestStatus.REQUESTED
)
}

export const getOutgoingPaymentRequests = (state: RootState) => {
return (state.account.outgoingPaymentRequests || []).filter(
(p) => p.status === PaymentRequestStatus.REQUESTED
)
}
1 change: 1 addition & 0 deletions packages/mobile/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export enum PaymentRequestStatus {
REQUESTED = 'REQUESTED',
COMPLETED = 'COMPLETED',
DECLINED = 'DECLINED',
CANCELLED = 'CANCELLED',
}

// TODO(Rossy) Find a better home for this
Expand Down
17 changes: 11 additions & 6 deletions packages/mobile/src/analytics/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,17 @@ export enum CustomEventNames {

// Request Money events
// request_select_cancel is captured in send_select_cancel
request_payment_continue = 'request_payment_continue',
request_payment_request = 'request_payment_request',
request_payment_decline = 'request_payment_decline',
request_payment_pay = 'request_payment_pay',
request_payment_edit = 'request_payment_edit',
request_payment_review = 'request_payment_review',
request_payment_continue = 'incoming_request_payment_continue',
request_payment_request = 'incoming_request_payment_request',
request_payment_edit = 'incoming_request_payment_edit',

incoming_request_payment_decline = 'incoming_request_payment_decline',
incoming_request_payment_pay = 'incoming_request_payment_pay',
incoming_request_payment_review = 'incoming_request_payment_review',

outgoing_request_payment_review = 'outgoing_request_payment_review',
outgoing_request_payment_remind = 'outgoing_request_payment_remind',
outgoing_request_payment_cancel = 'outgoing_request_payment_cancel',

// Escrowed payments
escrowed_payment_review = 'escrowed_payment_review',
Expand Down
1 change: 1 addition & 0 deletions packages/mobile/src/app/ErrorMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ export enum ErrorMessages {
CALCULATE_FEE_FAILED = 'calculateFeeFailed',
FAILED_TO_SWITCH_SYNC_MODES = 'failedToSwitchSyncModes',
SMS_ERROR = 'walletFlow5:SMSError',
PAYMENT_REQUEST_UPDATE_FAILED = 'paymentRequestFlow:paymentRequestUpdateFailed',
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function testStore(sentEscrowedPayments: EscrowedPayment[]) {
})
}

describe('PaymentRequestListScreen', () => {
describe('EscrowedPaymentListScreen', () => {
it('renders correctly with payments', () => {
const store = testStore(payments)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PaymentRequestListScreen renders correctly with no payments 1`] = `
exports[`EscrowedPaymentListScreen renders correctly with no payments 1`] = `
<SafeAreaView
style={
Object {
Expand Down Expand Up @@ -115,7 +115,7 @@ exports[`PaymentRequestListScreen renders correctly with no payments 1`] = `
</SafeAreaView>
`;

exports[`PaymentRequestListScreen renders correctly with payments 1`] = `
exports[`EscrowedPaymentListScreen renders correctly with payments 1`] = `
<SafeAreaView
style={
Object {
Expand Down
16 changes: 16 additions & 0 deletions packages/mobile/src/firebase/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PaymentRequest, PaymentRequestStatus } from 'src/account'
export enum Actions {
AUTHORIZED = 'FIREBASE/AUTHORIZED',
PAYMENT_REQUEST_UPDATE_STATUS = 'FIREBASE/PAYMENT_REQUEST_UPDATE_STATUS',
PAYMENT_REQUEST_UPDATE_NOTIFIED = 'FIREBASE/PAYMENT_REQUEST_UPDATE_NOTIFIED',
PAYMENT_REQUEST_WRITE = 'FIREBASE/PAYMENT_REQUEST_WRITE',
}

Expand All @@ -16,6 +17,12 @@ export interface UpdatePaymentRequestStatusAction {
status: PaymentRequestStatus
}

export interface UpdatePaymentRequestNotifiedAction {
type: Actions.PAYMENT_REQUEST_UPDATE_NOTIFIED
id: string
notified: boolean
}

export interface WritePaymentRequest {
type: Actions.PAYMENT_REQUEST_WRITE
paymentInfo: PaymentRequest
Expand All @@ -30,6 +37,15 @@ export const updatePaymentRequestStatus = (
status,
})

export const updatePaymentRequestNotified = (
id: string,
notified: boolean
): UpdatePaymentRequestNotifiedAction => ({
type: Actions.PAYMENT_REQUEST_UPDATE_NOTIFIED,
id,
notified,
})

export const writePaymentRequest = (paymentInfo: PaymentRequest): WritePaymentRequest => ({
type: Actions.PAYMENT_REQUEST_WRITE,
paymentInfo,
Expand Down
Loading

0 comments on commit d2ec8e8

Please sign in to comment.