mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-29 13:06:03 +10:00
Merge pull request #105 from sharetribe/create-stripe-account
Create Stripe account when posting a new listing
This commit is contained in:
commit
60ec9e9e5a
9 changed files with 118 additions and 55 deletions
|
|
@ -4,7 +4,7 @@ import EditListingForm from './EditListingForm';
|
|||
export const Empty = {
|
||||
component: EditListingForm,
|
||||
props: {
|
||||
images: [],
|
||||
stripeConnected: false,
|
||||
onImageUpload: values => {
|
||||
console.log(`onImageUpload with id (${values.id}) and file name (${values.file.name})`);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ export class EditListingFormComponent extends Component {
|
|||
saveActionMsg = 'Save listing',
|
||||
submitting,
|
||||
selectedPlace,
|
||||
stripeConnected,
|
||||
} = this.props;
|
||||
const titleRequiredMessage = intl.formatMessage({ id: 'EditListingForm.titleRequired' });
|
||||
const maxLengthMessage = intl.formatMessage(
|
||||
|
|
@ -186,6 +187,7 @@ export class EditListingFormComponent extends Component {
|
|||
const pricePlaceholderMessage = intl.formatMessage({ id: 'EditListingForm.pricePlaceholder' });
|
||||
|
||||
const country = selectedPlace ? selectedPlace.country : null;
|
||||
const showBankAccountField = !stripeConnected && country;
|
||||
const currency = config.currencyConfig.currency;
|
||||
|
||||
return (
|
||||
|
|
@ -253,7 +255,7 @@ export class EditListingFormComponent extends Component {
|
|||
validate={[required(descriptionRequiredMessage)]}
|
||||
/>
|
||||
|
||||
{country
|
||||
{showBankAccountField
|
||||
? <Field
|
||||
name="bankAccountToken"
|
||||
component={StripeBankAccountToken}
|
||||
|
|
@ -280,6 +282,7 @@ EditListingFormComponent.propTypes = {
|
|||
...formPropTypes,
|
||||
initData: shape({ title: string, description: string }),
|
||||
selectedPlace: propTypes.place,
|
||||
stripeConnected: bool.isRequired,
|
||||
intl: intlShape.isRequired,
|
||||
onImageUpload: func.isRequired,
|
||||
onUpdateImageOrder: func.isRequired,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ describe('EditListingForm', () => {
|
|||
onImageUpload={v => v}
|
||||
onSubmit={v => v}
|
||||
onUpdateImageOrder={v => v}
|
||||
stripeConnected={false}
|
||||
/>
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { showListingsSuccess as globalShowListingsSuccess } from '../../ducks/sdk.duck';
|
||||
import { createStripeAccount } from '../../ducks/user.duck';
|
||||
|
||||
const requestAction = actionType => params => ({ type: actionType, payload: { params } });
|
||||
|
||||
|
|
@ -143,11 +144,15 @@ export function requestShowListing(actionPayload) {
|
|||
export function requestCreateListing(data) {
|
||||
return (dispatch, getState, sdk) => {
|
||||
const { bankAccountToken, country, ...actionPayload } = data;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('TODO: call API with Stripe token:', bankAccountToken, 'and country:', country);
|
||||
dispatch(createListing(actionPayload));
|
||||
return sdk.listings
|
||||
.create(actionPayload)
|
||||
|
||||
const shouldCreateStripeAccount = bankAccountToken && country;
|
||||
const accountCreated = shouldCreateStripeAccount
|
||||
? dispatch(createStripeAccount(bankAccountToken, country))
|
||||
: Promise.resolve('already created');
|
||||
|
||||
return accountCreated
|
||||
.then(() => sdk.listings.create(actionPayload))
|
||||
.then(response => {
|
||||
const id = response.data.data.id.uuid;
|
||||
// Modify store to understand that we have created listing and can redirect away
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { types } from '../../util/sdkLoader';
|
|||
import { NamedRedirect, PageLayout } from '../../components';
|
||||
import { EditListingForm } from '../../containers';
|
||||
import { getListingsById } from '../../ducks/sdk.duck';
|
||||
import { fetchCurrentUser } from '../../ducks/Auth.duck';
|
||||
import { fetchCurrentUser } from '../../ducks/user.duck';
|
||||
import { createSlug } from '../../util/urlHelpers';
|
||||
import * as propTypes from '../../util/propTypes';
|
||||
import {
|
||||
|
|
@ -87,8 +87,9 @@ export class EditListingPageComponent extends Component {
|
|||
? intl.formatMessage({ id: 'EditListingPage.titleCreateListing' })
|
||||
: intl.formatMessage({ id: 'EditListingPage.titleEditListing' });
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('current user:', currentUser);
|
||||
const stripeConnected = currentUser && currentUser.attributes
|
||||
? currentUser.attributes.stripeConnected
|
||||
: false;
|
||||
|
||||
return (
|
||||
<PageLayout title={title}>
|
||||
|
|
@ -100,6 +101,7 @@ export class EditListingPageComponent extends Component {
|
|||
onSubmit={onSubmit(onCreateListing)}
|
||||
onUpdateImageOrder={onUpdateImageOrder}
|
||||
saveActionMsg={saveActionMsg}
|
||||
stripeConnected={stripeConnected}
|
||||
/>
|
||||
</PageLayout>
|
||||
);
|
||||
|
|
@ -147,7 +149,7 @@ const mapStateToProps = state => {
|
|||
return {
|
||||
page: state.EditListingPage,
|
||||
marketplaceData: state.data || {},
|
||||
currentUser: state.Auth.currentUser,
|
||||
currentUser: state.user.currentUser,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ exports[`EditListingPageComponent matches snapshot 1`] = `
|
|||
onImageUpload={[Function]}
|
||||
onSubmit={[Function]}
|
||||
onUpdateImageOrder={[Function]}
|
||||
saveActionMsg="Create listing" />
|
||||
saveActionMsg="Create listing"
|
||||
stripeConnected={false} />
|
||||
</Connect(withRouter(PageLayout))>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,6 @@ const authenticated = authInfo => authInfo.grantType === 'refresh_token';
|
|||
|
||||
// ================ Action types ================ //
|
||||
|
||||
export const USERS_ME_REQUEST = 'app/Auth/USERS_ME_REQUEST';
|
||||
export const USERS_ME_SUCCESS = 'app/Auth/USERS_ME_SUCCESS';
|
||||
export const USERS_ME_ERROR = 'app/Auth/USERS_ME_ERROR';
|
||||
|
||||
export const AUTH_INFO_REQUEST = 'app/Auth/AUTH_INFO_REQUEST';
|
||||
export const AUTH_INFO_SUCCESS = 'app/Auth/AUTH_INFO_SUCCESS';
|
||||
export const AUTH_INFO_ERROR = 'app/Auth/AUTH_INFO_ERROR';
|
||||
|
|
@ -27,10 +23,8 @@ export const LOGOUT_ERROR = 'app/Auth/LOGOUT_ERROR';
|
|||
// ================ Reducer ================ //
|
||||
|
||||
const initialState = {
|
||||
currentUser: null,
|
||||
authInfoLoaded: false,
|
||||
isAuthenticated: false,
|
||||
currentUserError: null,
|
||||
authInfoError: null,
|
||||
loginError: null,
|
||||
logoutError: null,
|
||||
|
|
@ -39,13 +33,6 @@ const initialState = {
|
|||
export default function reducer(state = initialState, action = {}) {
|
||||
const { type, payload } = action;
|
||||
switch (type) {
|
||||
case USERS_ME_REQUEST:
|
||||
return { ...state, currentUserError: null };
|
||||
case USERS_ME_SUCCESS:
|
||||
return { ...state, currentUser: payload };
|
||||
case USERS_ME_ERROR:
|
||||
return { ...state, currentUserError: payload };
|
||||
|
||||
case AUTH_INFO_REQUEST:
|
||||
return { ...state, authInfoError: null };
|
||||
case AUTH_INFO_SUCCESS:
|
||||
|
|
@ -73,19 +60,6 @@ export default function reducer(state = initialState, action = {}) {
|
|||
|
||||
// ================ Action creators ================ //
|
||||
|
||||
export const usersMeRequest = () => ({ type: USERS_ME_REQUEST });
|
||||
|
||||
export const usersMeSuccess = user => ({
|
||||
type: USERS_ME_SUCCESS,
|
||||
payload: user,
|
||||
});
|
||||
|
||||
export const usersMeError = e => ({
|
||||
type: USERS_ME_ERROR,
|
||||
payload: e,
|
||||
error: true,
|
||||
});
|
||||
|
||||
export const authInfo = () => ({ type: AUTH_INFO_REQUEST });
|
||||
export const authInfoSuccess = info => ({ type: AUTH_INFO_SUCCESS, payload: info });
|
||||
export const authInfoError = error => ({ type: AUTH_INFO_ERROR, payload: error, error: true });
|
||||
|
|
@ -162,20 +136,3 @@ export function* watchAuth(sdk) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================ Thunks ================ //
|
||||
|
||||
export const fetchCurrentUser = () =>
|
||||
(dispatch, getState, sdk) => {
|
||||
dispatch(usersMeRequest());
|
||||
return sdk.users
|
||||
.me()
|
||||
.then(response => {
|
||||
dispatch(usersMeSuccess(response.data.data));
|
||||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(usersMeError(e));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,5 +9,6 @@ import Auth from './Auth.duck';
|
|||
import FlashNotification from './FlashNotification.duck';
|
||||
import LocationFilter from './LocationFilter.duck';
|
||||
import sdkReducer from './sdk.duck';
|
||||
import user from './user.duck';
|
||||
|
||||
export { form, Auth, FlashNotification, LocationFilter, sdkReducer as data };
|
||||
export { form, Auth, FlashNotification, LocationFilter, sdkReducer as data, user };
|
||||
|
|
|
|||
93
src/ducks/user.duck.js
Normal file
93
src/ducks/user.duck.js
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// ================ Action types ================ //
|
||||
|
||||
export const USERS_ME_REQUEST = 'app/user/USERS_ME_REQUEST';
|
||||
export const USERS_ME_SUCCESS = 'app/user/USERS_ME_SUCCESS';
|
||||
export const USERS_ME_ERROR = 'app/user/USERS_ME_ERROR';
|
||||
|
||||
export const STRIPE_ACCOUNT_CREATE_REQUEST = 'app/user/STRIPE_ACCOUNT_CREATE_REQUEST';
|
||||
export const STRIPE_ACCOUNT_CREATE_SUCCESS = 'app/user/STRIPE_ACCOUNT_CREATE_SUCCESS';
|
||||
export const STRIPE_ACCOUNT_CREATE_ERROR = 'app/user/STRIPE_ACCOUNT_CREATE_ERROR';
|
||||
|
||||
// ================ Reducer ================ //
|
||||
|
||||
const initialState = {
|
||||
currentUser: null,
|
||||
usersMeError: null,
|
||||
};
|
||||
|
||||
export default function reducer(state = initialState, action = {}) {
|
||||
const { type, payload } = action;
|
||||
switch (type) {
|
||||
case USERS_ME_REQUEST:
|
||||
return { ...state, usersMeError: null };
|
||||
case USERS_ME_SUCCESS:
|
||||
return { ...state, currentUser: payload };
|
||||
case USERS_ME_ERROR:
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(payload);
|
||||
return { ...state, usersMeError: payload };
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
// ================ Action creators ================ //
|
||||
|
||||
export const usersMeRequest = () => ({ type: USERS_ME_REQUEST });
|
||||
|
||||
export const usersMeSuccess = user => ({
|
||||
type: USERS_ME_SUCCESS,
|
||||
payload: user,
|
||||
});
|
||||
|
||||
export const usersMeError = e => ({
|
||||
type: USERS_ME_ERROR,
|
||||
payload: e,
|
||||
error: true,
|
||||
});
|
||||
|
||||
export const stripeAccountCreateRequest = () => ({ type: STRIPE_ACCOUNT_CREATE_REQUEST });
|
||||
|
||||
export const stripeAccountCreateSuccess = response => ({
|
||||
type: STRIPE_ACCOUNT_CREATE_SUCCESS,
|
||||
payload: response,
|
||||
});
|
||||
|
||||
export const stripeAccountCreateError = e => ({
|
||||
type: STRIPE_ACCOUNT_CREATE_ERROR,
|
||||
payload: e,
|
||||
error: true,
|
||||
});
|
||||
|
||||
// ================ Thunks ================ //
|
||||
|
||||
export const fetchCurrentUser = () =>
|
||||
(dispatch, getState, sdk) => {
|
||||
dispatch(usersMeRequest());
|
||||
return sdk.users
|
||||
.me()
|
||||
.then(response => {
|
||||
dispatch(usersMeSuccess(response.data.data));
|
||||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(usersMeError(e));
|
||||
throw e;
|
||||
});
|
||||
};
|
||||
|
||||
export const createStripeAccount = (bankAccountToken, country) =>
|
||||
(dispatch, getState, sdk) => {
|
||||
dispatch(stripeAccountCreateRequest());
|
||||
return sdk.users.createStripeAccount({ bankAccountToken, country })
|
||||
.then(response => {
|
||||
dispatch(stripeAccountCreateSuccess(response));
|
||||
return response;
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(stripeAccountCreateError(e));
|
||||
throw e;
|
||||
})
|
||||
.then(() => dispatch(fetchCurrentUser()));
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue