Add StripePaymentForm to the CheckoutPage

- Remove hardcoded UI components
 - Hardcode a temporary listing object
 - Add StripePaymentForm component
 - Style as in wireframe designs
This commit is contained in:
Kimmo Puputti 2017-04-06 16:43:32 +03:00
parent 31b3155304
commit a80f84ff64
7 changed files with 91 additions and 79 deletions

View file

@ -41,7 +41,7 @@ describe('Application', () => {
'/s/map': 'Search page: map',
'/l/listing-title-slug/1234': 'Loading listing data',
'/u/1234': 'Profile page with display name: 1234',
'/checkout/1234': 'Book Banyan Studios (1234)',
'/checkout': 'Book Example listing',
'/login': 'Authentication page: login tab',
'/signup': 'Authentication page: signup tab',
'/password': 'Request new password',
@ -87,7 +87,7 @@ describe('Application', () => {
});
it('redirects to correct URLs', () => {
const urlRedirects = { '/l': '/', '/u': '/', '/checkout': '/' };
const urlRedirects = { '/l': '/', '/u': '/' };
forEach(urlRedirects, (redirectPath, url) => {
const context = {};
const { body } = render(url, context);

View file

@ -1,21 +1,12 @@
.buttonLink {
display: block;
width: 100%;
font-size: 1.4rem;
padding: 0.5rem;
margin: 1rem 0;
background-color: #eee;
border: 1px solid #ddd;
cursor: pointer;
text-align: center;
text-decoration: none;
color: #000;
&:hover {
background-color: #ddd;
}
&:active {
background-color: #ccc;
}
.title {
margin: 1rem;
}
.payment {
padding: 0 1rem;
}
.paymentTitle {
font-size: 1rem;
margin: 1rem 0 0 0;
}

View file

@ -1,35 +1,60 @@
import React, { PropTypes } from 'react';
import { BookingInfo, PageLayout, NamedLink } from '../../components';
import React from 'react';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { types } from '../../util/sdkLoader';
import { PageLayout } from '../../components';
import { StripePaymentForm } from '../../containers';
import css from './CheckoutPage.css';
const CheckoutPage = props => {
const { params } = props;
const { listingId } = params;
const { UUID, LatLng } = types;
const info = {
title: 'Banyan Studios',
imageUrl: 'http://placehold.it/750x470',
pricePerDay: '55\u20AC',
bookingPeriod: 'Jan 2nd - Jan 4th',
bookingDuration: '3 days',
total: '165\u20AC',
export const CheckoutPageComponent = props => {
const { intl } = props;
const listing = {
id: new UUID('00000000-0000-0000-0000-000000000000'),
type: 'listing',
attributes: {
title: 'Example listing',
description: 'Listing description here.',
address: 'Helsinki, Finland',
geolocation: new LatLng(60.16985569999999, 24.93837899999994),
},
};
const imageUrl = 'https://placehold.it/750x470';
const title = intl.formatMessage(
{
id: 'CheckoutPage.title',
},
{
listingTitle: listing.attributes.title,
}
);
const handleSubmit = token => {
// eslint-disable-next-line no-console
console.log('submit token:', token);
};
return (
<PageLayout title={`Book ${info.title} (${listingId})`}>
<img alt={info.title} src={info.imageUrl} style={{ width: '100%' }} />
<BookingInfo {...info} />
<p>By confirming I accept the booking terms and conditions.</p>
<NamedLink className={css.buttonLink} name="OrderDetailsPage" params={{ id: 12345 }}>
Confirm & Pay
</NamedLink>
<PageLayout title={title}>
<h1 className={css.title}>{title}</h1>
<img alt={listing.attributes.title} src={imageUrl} style={{ width: '100%' }} />
<section className={css.payment}>
<h2 className={css.paymentTitle}>
<FormattedMessage id="CheckoutPage.paymentTitle" />
</h2>
<p>
<FormattedMessage id="CheckoutPage.paymentInfo" />
</p>
<StripePaymentForm onSubmit={handleSubmit} />
</section>
</PageLayout>
);
};
const { shape, string } = PropTypes;
CheckoutPageComponent.propTypes = {
intl: intlShape.isRequired,
};
CheckoutPage.propTypes = { params: shape({ listingId: string.isRequired }).isRequired };
export default CheckoutPage;
export default injectIntl(CheckoutPageComponent);

View file

@ -1,10 +1,13 @@
import React from 'react';
import { renderShallow } from '../../util/test-helpers';
import CheckoutPage from './CheckoutPage';
import { fakeIntl } from '../../util/test-data';
import { CheckoutPageComponent } from './CheckoutPage';
describe('CheckoutPage', () => {
it('matches snapshot', () => {
const tree = renderShallow(<CheckoutPage params={{ listingId: 'some-listing-id' }} />);
const tree = renderShallow(
<CheckoutPageComponent intl={fakeIntl}/>
);
expect(tree).toMatchSnapshot();
});
});

View file

@ -1,32 +1,30 @@
exports[`CheckoutPage matches snapshot 1`] = `
<Connect(withRouter(PageLayout))
title="Book Banyan Studios (some-listing-id)">
title="CheckoutPage.title">
<h1>
CheckoutPage.title
</h1>
<img
alt="Banyan Studios"
src="http://placehold.it/750x470"
alt="Example listing"
src="https://placehold.it/750x470"
style={
Object {
"width": "100%",
}
} />
<BookingInfo
bookingDuration="3 days"
bookingPeriod="Jan 2nd - Jan 4th"
imageUrl="http://placehold.it/750x470"
pricePerDay="55€"
title="Banyan Studios"
total="165€" />
<p>
By confirming I accept the booking terms and conditions.
</p>
<withFlattenedRoutes(withRouter(NamedLink))
name="OrderDetailsPage"
params={
Object {
"id": 12345,
}
}>
Confirm & Pay
</withFlattenedRoutes(withRouter(NamedLink))>
<section>
<h2>
<FormattedMessage
id="CheckoutPage.paymentTitle"
values={Object {}} />
</h2>
<p>
<FormattedMessage
id="CheckoutPage.paymentInfo"
values={Object {}} />
</p>
<InjectIntl(StripePaymentForm)
onSubmit={[Function]} />
</section>
</Connect(withRouter(PageLayout))>
`;

View file

@ -111,16 +111,8 @@ const routesConfiguration = [
{
path: '/checkout',
exact: true,
name: 'CheckoutBasePage',
component: RedirectToLandingPage,
routes: [
{
path: '/checkout/:listingId',
exact: true,
name: 'CheckoutPage',
component: props => <CheckoutPage {...props} />,
},
],
name: 'CheckoutPage',
component: props => <CheckoutPage {...props} />,
},
{
path: '/login',

View file

@ -1,6 +1,9 @@
{
"AuthenticationPage.loginFailed": "The email and password you entered did not match our records. Please double-check and try again.",
"AuthenticationPage.loginRequiredFor": "You must log in to view the page at",
"CheckoutPage.title": "Book {listingTitle}",
"CheckoutPage.paymentTitle": "Payment",
"CheckoutPage.paymentInfo": "You'll only be charged if your request is accepted by the provider.",
"EditListingForm.bankAccountNumberRequired": "You need to add a bank account number.",
"EditListingForm.descriptionRequired": "You need to add a description.",
"EditListingForm.imageRequired": "You need to add at least one image.",