Use proper listing and user shapes in card components

This commit is contained in:
Kimmo Puputti 2017-02-23 13:39:17 +02:00
parent 4066948800
commit 081e56c99f
6 changed files with 55 additions and 81 deletions

View file

@ -1,10 +1,22 @@
import React, { PropTypes } from 'react';
import React from 'react';
import { NamedLink } from '../../components';
import * as propTypes from '../../util/propTypes';
import css from './ListingCard.css';
const ListingCard = props => {
const { id, title, price, description, location, review, author } = props;
const { listing } = props;
const id = listing.id.uuid;
const { title, description, address } = listing.attributes;
const slug = encodeURIComponent(title.split(' ').join('-'));
const authorName = `${listing.author.attributes.profile.firstName} ${listing.author.attributes.profile.lastName}`;
// TODO: these are not yet present in the API data, figure out what
// to do with them
const price = '55\u20AC / day';
const review = { rating: 3, count: 10 };
const authorAvatar = 'http://placehold.it/44x44';
const authorReview = { rating: 4 };
return (
<div className={css.listing}>
<div className={css.squareWrapper}>
@ -26,22 +38,22 @@ const ListingCard = props => {
</div>
<div className={css.details}>
<div className={css.location}>
{location}
{address}
</div>
<div className={css.reviews}>
(<span>{review.rating}</span><span>/5</span>){' '}
<span>{review.count}</span>
<span>{review.count} reviews</span>
</div>
</div>
<hr />
<div className={css.authorInfo}>
<div className={css.avatarWrapper}>
<img className={css.avatar} src={author.avatar} alt={author.name} />
<img className={css.avatar} src={authorAvatar} alt={authorName} />
</div>
<div className={css.authorDetails}>
<span className={css.authorName}>{author.name}</span>
<span className={css.authorName}>{authorName}</span>
<div className={css.authorReview}>
review: <span>{author.review.rating}</span><span>/5</span>
review: <span>{authorReview.rating}</span><span>/5</span>
</div>
</div>
</div>
@ -50,22 +62,6 @@ const ListingCard = props => {
);
};
ListingCard.defaultProps = { location: null, review: {}, author: {} };
const { shape, string } = PropTypes;
ListingCard.propTypes = {
id: string.isRequired,
title: string.isRequired,
price: string.isRequired,
description: string.isRequired,
location: string,
review: shape({ rating: string.isRequired, count: string.isRequired }),
author: shape({
name: string.isRequired,
avatar: string.isRequired,
review: shape({ rating: string.isRequired }),
}),
};
ListingCard.propTypes = { listing: propTypes.listing.isRequired };
export default ListingCard;

View file

@ -1,23 +1,12 @@
import React from 'react';
import { renderShallow } from '../../util/test-helpers';
import { renderShallow, createUser, createListing } from '../../util/test-helpers';
import ListingCard from './ListingCard';
describe('ListingCard', () => {
it('matches snapshot', () => {
const listing = {
id: 'some-id',
title: 'Banyan Studios',
price: '55\u20AC / day',
description: 'Organic Music Production in a Sustainable, Ethical and Professional Studio.',
location: 'New York, NY \u2022 40mi away',
review: { count: '8 reviews', rating: '4' },
author: {
name: 'The Stardust Collective',
avatar: 'http://placehold.it/44x44',
review: { rating: '4' },
},
};
const tree = renderShallow(<ListingCard {...listing} />);
const author = createUser('user1');
const listing = { ...createListing('listing1'), author };
const tree = renderShallow(<ListingCard listing={listing} />);
expect(tree).toMatchSnapshot();
});
});

View file

@ -13,27 +13,27 @@ exports[`ListingCard matches snapshot 1`] = `
name="ListingPage"
params={
Object {
"id": "some-id",
"slug": "Banyan-Studios",
"id": "listing1",
"slug": "listing1-title",
}
}>
Banyan Studios
listing1 title
</withFlattenedRoutes(withRouter(NamedLink))>
<div>
55€ / day
</div>
</div>
<div>
Organic Music Production in a Sustainable, Ethical and Professional Studio.
listing1 description
</div>
<div>
<div>
New York, NY • 40mi away
listing1 address
</div>
<div>
(
<span>
4
3
</span>
<span>
/5
@ -41,7 +41,8 @@ exports[`ListingCard matches snapshot 1`] = `
)
<span>
8 reviews
10
reviews
</span>
</div>
</div>
@ -49,12 +50,12 @@ exports[`ListingCard matches snapshot 1`] = `
<div>
<div>
<img
alt="The Stardust Collective"
alt="user1 first name user1 last name"
src="http://placehold.it/44x44" />
</div>
<div>
<span>
The Stardust Collective
user1 first name user1 last name
</span>
<div>
review:

View file

@ -1,11 +1,19 @@
import React, { PropTypes } from 'react';
import React from 'react';
import { NamedLink } from '../../components';
import * as propTypes from '../../util/propTypes';
import css from './ListingCardSmall.css';
// <NamedLink name="SearchListingsPage">X</NamedLink>
const ListingCardSmall = props => {
const { id, title, price, review } = props;
const { listing } = props;
const title = listing.attributes.title;
const id = listing.id.uuid;
const slug = encodeURIComponent(title.split(' ').join('-'));
// TODO: these are not yet present in the API data, figure out what
// to do with them
const price = '55\u20AC / day';
const review = { rating: 3, count: 10 };
return (
<div className={css.listing}>
<div className={css.squareWrapper}>
@ -29,15 +37,6 @@ const ListingCardSmall = props => {
);
};
ListingCardSmall.defaultProps = { review: {} };
const { number, shape, string } = PropTypes;
ListingCardSmall.propTypes = {
id: number.isRequired,
title: string.isRequired,
price: string.isRequired,
review: shape({ rating: string.isRequired, count: string.isRequired }),
};
ListingCardSmall.propTypes = { listing: propTypes.listing.isRequired };
export default ListingCardSmall;

View file

@ -1,23 +1,12 @@
import React from 'react';
import { renderShallow } from '../../util/test-helpers';
import { renderShallow, createUser, createListing } from '../../util/test-helpers';
import ListingCardSmall from './ListingCardSmall';
describe('ListingCardSmall', () => {
it('matches snapshot', () => {
const listing = {
id: 123,
title: 'Banyan Studios',
price: '55\u20AC / day',
description: 'Organic Music Production in a Sustainable, Ethical and Professional Studio.',
location: 'New York, NY \u2022 40mi away',
review: { count: '8 reviews', rating: '4' },
author: {
name: 'The Stardust Collective',
avatar: 'http://placehold.it/44x44',
review: { rating: '4' },
},
};
const tree = renderShallow(<ListingCardSmall {...listing} />);
const author = createUser('user1');
const listing = { ...createListing('listing1'), author };
const tree = renderShallow(<ListingCardSmall listing={listing} />);
expect(tree).toMatchSnapshot();
});
});

View file

@ -12,16 +12,16 @@ exports[`ListingCardSmall matches snapshot 1`] = `
name="ListingPage"
params={
Object {
"id": 123,
"slug": "Banyan-Studios",
"id": "listing1",
"slug": "listing1-title",
}
}>
Banyan Studios
listing1 title
</withFlattenedRoutes(withRouter(NamedLink))>
<div>
(
<span>
4
3
</span>
<span>
/5
@ -29,7 +29,7 @@ exports[`ListingCardSmall matches snapshot 1`] = `
)
<span>
8 reviews
10
</span>
</div>
<div>