From 1fdccf7f7143e6fdfd2deca1a9693ee37077659c Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Thu, 26 Jan 2017 16:13:24 +0200 Subject: [PATCH] ListingCard for SearchResultsPanel and ListingCardSmall for MapPanel --- src/components/ListingCard/ListingCard.css | 67 +++++++++++++++ src/components/ListingCard/ListingCard.js | 71 +++++++++++++++ .../ListingCard/ListingCard.test.js | 35 ++++++++ .../__snapshots__/ListingCard.test.js.snap | 86 +++++++++++++++++++ .../ListingCardSmall/ListingCardSmall.css | 38 ++++++++ .../ListingCardSmall/ListingCardSmall.js | 43 ++++++++++ .../ListingCardSmall/ListingCardSmall.test.js | 35 ++++++++ .../ListingCardSmall.test.js.snap | 44 ++++++++++ 8 files changed, 419 insertions(+) create mode 100644 src/components/ListingCard/ListingCard.css create mode 100644 src/components/ListingCard/ListingCard.js create mode 100644 src/components/ListingCard/ListingCard.test.js create mode 100644 src/components/ListingCard/__snapshots__/ListingCard.test.js.snap create mode 100644 src/components/ListingCardSmall/ListingCardSmall.css create mode 100644 src/components/ListingCardSmall/ListingCardSmall.js create mode 100644 src/components/ListingCardSmall/ListingCardSmall.test.js create mode 100644 src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap diff --git a/src/components/ListingCard/ListingCard.css b/src/components/ListingCard/ListingCard.css new file mode 100644 index 00000000..bafa1e92 --- /dev/null +++ b/src/components/ListingCard/ListingCard.css @@ -0,0 +1,67 @@ +.listing { + display: flex; + flex-direction: column; + border-radius: 4px; +} + +.squareWrapper { + display: block; + position: relative; + width: 100%; +} + +/* Firefox doesn't support image aspect ratio inside flexbox */ +.aspectWrapper { + padding-bottom: 75%; /* 4:3 Aspect Ratio */ +} + +.thumbnail { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; +} + +.info { + padding: 1rem; + +} + +.mainInfo { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.details { + width: 100%; + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.authorInfo { + width: 100%; + display: flex; + flex-direction: row; +} + +.authorDetails { + width: 100%; + display: flex; + flex-direction: column; +} +.avatarWrapper { + display: block; + flex-basis: 44px; + width: 44px; + height: 44px; + margin-right: 1rem; +} +.avatar { + border-radius: 22px; +} diff --git a/src/components/ListingCard/ListingCard.js b/src/components/ListingCard/ListingCard.js new file mode 100644 index 00000000..a868367d --- /dev/null +++ b/src/components/ListingCard/ListingCard.js @@ -0,0 +1,71 @@ +import React, { PropTypes } from 'react'; +import { NamedLink } from '../../components'; +import css from './ListingCard.css'; + +const ListingCard = props => { + const { id, title, price, description, location, review, author } = props; + const slug = encodeURIComponent(title.split(' ').join('-')); + return ( +
+
+
+ Listing Title +
+
+
+
+ + {title} + +
+ {price} +
+
+
+ {description} +
+
+
+ {location} +
+
+ ({review.rating}/5){' '} + {review.count} +
+
+
+
+
+ {author.name} +
+
+ {author.name} +
+ review: {author.review.rating}/5 +
+
+
+
+
+ ); +}; + +ListingCard.defaultProps = { location: null, review: {}, author: {} }; + +const { number, shape, string } = PropTypes; + +ListingCard.propTypes = { + id: number.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 }), + }), +}; + +export default ListingCard; diff --git a/src/components/ListingCard/ListingCard.test.js b/src/components/ListingCard/ListingCard.test.js new file mode 100644 index 00000000..c016fffe --- /dev/null +++ b/src/components/ListingCard/ListingCard.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { TestProvider } from '../../util/test-helpers'; +import { RoutesProvider } from '../../components'; +import routesConfiguration from '../../routesConfiguration'; +import ListingCard from './ListingCard'; + +describe('ListingCard', () => { + 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 component = renderer.create( + ( + + + + + + ), + ); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/ListingCard/__snapshots__/ListingCard.test.js.snap b/src/components/ListingCard/__snapshots__/ListingCard.test.js.snap new file mode 100644 index 00000000..2c06adbf --- /dev/null +++ b/src/components/ListingCard/__snapshots__/ListingCard.test.js.snap @@ -0,0 +1,86 @@ +exports[`ListingCard matches snapshot 1`] = ` +
+
+
+ Listing Title +
+
+
+
+ + Banyan Studios + +
+ 55€ / day +
+
+
+ Organic Music Production in a Sustainable, Ethical and Professional Studio. +
+
+
+ New York, NY • 40mi away +
+
+ ( + + 4 + + + /5 + + ) + + + 8 reviews + +
+
+
+
+
+ The Stardust Collective +
+
+ + The Stardust Collective + +
+ review: + + 4 + + + /5 + +
+
+
+
+
+`; diff --git a/src/components/ListingCardSmall/ListingCardSmall.css b/src/components/ListingCardSmall/ListingCardSmall.css new file mode 100644 index 00000000..4ac667ed --- /dev/null +++ b/src/components/ListingCardSmall/ListingCardSmall.css @@ -0,0 +1,38 @@ +.listing { + width: 130px; + display: flex; + flex-direction: column; + border-radius: 4px; + margin-right: 1rem; +} + +.squareWrapper { + display: block; + position: relative; + width: 100%; +} + +/* Firefox doesn't support image aspect ratio inside flexbox */ +.aspectWrapper { + padding-bottom: 75%; /* 4:3 Aspect Ratio */ +} + +.thumbnail { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; +} + +.info { + width: 100%; + display: flex; + flex-direction: column; + justify-content: space-between; + padding: 0.5rem; + font-size: 0.8rem; + border: solid 1px #ccc; +} diff --git a/src/components/ListingCardSmall/ListingCardSmall.js b/src/components/ListingCardSmall/ListingCardSmall.js new file mode 100644 index 00000000..c4578dd0 --- /dev/null +++ b/src/components/ListingCardSmall/ListingCardSmall.js @@ -0,0 +1,43 @@ +import React, { PropTypes } from 'react'; +import { NamedLink } from '../../components'; +import css from './ListingCardSmall.css'; + +// X +const ListingCardSmall = props => { + const { id, title, price, review } = props; + const slug = encodeURIComponent(title.split(' ').join('-')); + return ( +
+
+
+ Listing Title +
+
+
+ + {title} + +
+ ({review.rating}/5){' '} + {review.count} +
+
+ {price} +
+
+
+ ); +}; + +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 }), +}; + +export default ListingCardSmall; diff --git a/src/components/ListingCardSmall/ListingCardSmall.test.js b/src/components/ListingCardSmall/ListingCardSmall.test.js new file mode 100644 index 00000000..2f5e2eb1 --- /dev/null +++ b/src/components/ListingCardSmall/ListingCardSmall.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { TestProvider } from '../../util/test-helpers'; +import { RoutesProvider } from '../../components'; +import routesConfiguration from '../../routesConfiguration'; +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 component = renderer.create( + ( + + + + + + ), + ); + const tree = component.toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap b/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap new file mode 100644 index 00000000..e6a52348 --- /dev/null +++ b/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap @@ -0,0 +1,44 @@ +exports[`ListingCardSmall matches snapshot 1`] = ` +
+
+
+ Listing Title +
+
+
+ + Banyan Studios + +
+ ( + + 4 + + + /5 + + ) + + + 8 reviews + +
+
+ 55€ / day +
+
+
+`;