feat: add Stripe card form (#43433)

* eat: add Stripe card form

* Apply suggestions from code review

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

* feat: adjust payload and error handling

* feat:  readjust error handling

* Apply suggestions from code review

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

* feat: refactors from comments

* feat: prevent submition during processing

* feat: redefine isSubmitting

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>

* fix: show the proper paypal button on donate page

* fix: handle errors from stripe

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
Co-authored-by: moT01 <20648924+moT01@users.noreply.github.com>
This commit is contained in:
Ahmad Abdolsaheb
2021-09-17 22:15:56 +03:00
committed by GitHub
parent 2dd106eb2f
commit e5523bf16e
14 changed files with 476 additions and 51 deletions

View File

@@ -28,7 +28,7 @@ export const actionTypes = createTypes(
...createAsyncTypes('acceptTerms'),
...createAsyncTypes('showCert'),
...createAsyncTypes('reportUser'),
...createAsyncTypes('postChargeStripe')
...createAsyncTypes('postChargeStripeCard')
],
ns
);

View File

@@ -7,7 +7,11 @@ import {
call,
take
} from 'redux-saga/effects';
import { addDonation, postChargeStripe } from '../utils/ajax';
import {
addDonation,
postChargeStripe,
postChargeStripeCard
} from '../utils/ajax';
import { actionTypes as appTypes } from './action-types';
import {
@@ -19,10 +23,12 @@ import {
addDonationComplete,
addDonationError,
postChargeStripeComplete,
postChargeStripeError
postChargeStripeError,
postChargeStripeCardComplete,
postChargeStripeCardError
} from './';
const defaultDonationError = `Something is not right. Please contact donors@freecodecamp.org`;
const defaultDonationErrorMessage = `Something is not right. Please contact donors@freecodecamp.org`;
function* showDonateModalSaga() {
let shouldRequestDonation = yield select(shouldRequestDonationSelector);
@@ -48,7 +54,7 @@ function* addDonationSaga({ payload }) {
error.response && error.response.data
? error.response.data
: {
message: defaultDonationError
message: defaultDonationErrorMessage
};
yield put(addDonationError(data.message));
}
@@ -62,15 +68,27 @@ function* postChargeStripeSaga({ payload }) {
const err =
error.response && error.response.data
? error.response.data.error
: defaultDonationError;
: defaultDonationErrorMessage;
yield put(postChargeStripeError(err));
}
}
function* postChargeStripeCardSaga({ payload }) {
try {
const { error } = yield call(postChargeStripeCard, payload);
if (error) throw error;
yield put(postChargeStripeCardComplete());
} catch (error) {
const errorMessage = error.message || defaultDonationErrorMessage;
yield put(postChargeStripeCardError(errorMessage));
}
}
export function createDonationSaga(types) {
return [
takeEvery(types.tryToShowDonationModal, showDonateModalSaga),
takeEvery(types.addDonation, addDonationSaga),
takeLeading(types.postChargeStripe, postChargeStripeSaga)
takeLeading(types.postChargeStripe, postChargeStripeSaga),
takeLeading(types.postChargeStripeCard, postChargeStripeCardSaga)
];
}

View File

@@ -136,6 +136,15 @@ export const postChargeStripeComplete = createAction(
export const postChargeStripeError = createAction(
actionTypes.postChargeStripeError
);
export const postChargeStripeCard = createAction(
actionTypes.postChargeStripeCard
);
export const postChargeStripeCardComplete = createAction(
actionTypes.postChargeStripeCardComplete
);
export const postChargeStripeCardError = createAction(
actionTypes.postChargeStripeCardError
);
export const fetchProfileForUser = createAction(
actionTypes.fetchProfileForUser
@@ -450,6 +459,29 @@ export const reducer = handleActions(
...state,
donationFormState: { ...defaultDonationFormState, error: payload }
}),
[actionTypes.postChargeStripeCard]: state => ({
...state,
donationFormState: { ...defaultDonationFormState, processing: true }
}),
[actionTypes.postChargeStripeCardComplete]: state => {
const { appUsername } = state;
return {
...state,
user: {
...state.user,
[appUsername]: {
...state.user[appUsername],
isDonating: true
}
},
donationFormState: { ...defaultDonationFormState, success: true }
};
},
[actionTypes.postChargeStripeCardError]: (state, { payload }) => ({
...state,
donationFormState: { ...defaultDonationFormState, error: payload }
}),
[actionTypes.fetchUser]: state => ({
...state,
userFetchState: { ...defaultFetchState }