mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-28 12:43:11 +10:00
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:
parent
31b3155304
commit
a80f84ff64
7 changed files with 91 additions and 79 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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))>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue