From ab7666968d98909f9a9179f6d11cc97fe539d264 Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Fri, 3 Mar 2017 17:49:06 +0200 Subject: [PATCH] ListingPage: fetch & redux --- src/containers/ListingPage/ListingPage.js | 204 ++++++++++++++-------- 1 file changed, 127 insertions(+), 77 deletions(-) diff --git a/src/containers/ListingPage/ListingPage.js b/src/containers/ListingPage/ListingPage.js index 4fdfcb5b..55d6d0f7 100644 --- a/src/containers/ListingPage/ListingPage.js +++ b/src/containers/ListingPage/ListingPage.js @@ -1,9 +1,13 @@ -import React from 'react'; +import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { types } from 'sharetribe-sdk'; import { NamedLink, PageLayout } from '../../components'; +import { showListings, getListingsById } from '../../ducks/sdk.duck'; import css from './ListingPage.css'; +// TODO this hard coded info needs to be removed when API supports these features const info = { - title: 'Banyan Studios', + //title: 'Banyan Studios', price: '55\u20AC / day', images: [ { id: 1, title: 'img1', imageUrl: 'http://placehold.it/750x470' }, @@ -12,18 +16,18 @@ const info = { { id: 4, title: 'img4', imageUrl: 'http://placehold.it/750x470' }, { id: 5, title: 'img5', imageUrl: 'http://placehold.it/750x470' }, ], - description: ` -

- Organic Music Production in a Sustainable, Ethical and Professional Studio. -

-

- Social Permaculture focuses on nourishing our environment with abundance instead of depleting it. -

-

- Banyan Studios is a comfortable, conscious, inspiring and creative retreat for musicians trying to convey their message through state of the art Audio & Video. -

- https://vimeo.com/168106603 - `, + // description: ` + //

+ // Organic Music Production in a Sustainable, Ethical and Professional Studio. + //

+ //

+ // Social Permaculture focuses on nourishing our environment with abundance instead of depleting it. + //

+ //

+ // Banyan Studios is a comfortable, conscious, inspiring and creative retreat for musicians trying to convey their message through state of the art Audio & Video. + //

+ // https://vimeo.com/168106603 + // `, reviews: [ { id: 1, @@ -39,67 +43,113 @@ const info = { }; // N.B. All the presentational content needs to be extracted to their own components -const ListingPage = () => ( - -
- {info.images[0].title} -
- {info.images.slice(1).map(image => ( -
-
- {image.title} -
-
- ))} -
-
- {/* eslint-disable react/no-danger */} -
- {/* eslint-enable react/no-danger */} -
-

Here will be filters (or dragons)

-

Studio type

-

Amenities

-

Additional Services Available

-

Studio hours: 10am - 6pm

-
- -

Contact studio

-
-
-

Studio reviews (1)

-
- {info.reviews.map(review => ( -
-

{review.review}

-
-
- {review.reviewer.name} -
-
- {review.reviewer.name} - {review.reviewer.date} - -
-
- review: {review.rating}/5 -
-
-
- ))} -
-
-
Map
- - {`Book ${info.title}`} - - -); +export class ListingPageComponent extends Component { -export default ListingPage; + componentDidMount() { + ListingPageComponent.loadData(this.props.params.id, this.props.onLoadListing); + } + + render() { + const { entitiesData, params } = this.props; + const id = new types.UUID(params.id); + const currentListing = entitiesData.entities.listing ? getListingsById(entitiesData, [id])[0] : null; + + const title = currentListing ? currentListing.attributes.title : ''; + const description = currentListing ? currentListing.attributes.description : ''; + + // TODO render "loading" or blank page, if currentListing is null. + return ( + +
+ {info.images[0].title} +
+ {info.images.slice(1).map(image => ( +
+
+ {image.title} +
+
+ ))} +
+
+ {/* eslint-disable react/no-danger */} +
+ {/* eslint-enable react/no-danger */} +
+

Here will be filters (or dragons)

+

Studio type

+

Amenities

+

Additional Services Available

+

Studio hours: 10am - 6pm

+
+ +

Contact studio

+
+
+

Studio reviews (1)

+
+ {info.reviews.map(review => ( +
+

{review.review}

+
+
+ {review.reviewer.name} +
+
+ {review.reviewer.name} + {review.reviewer.date} + +
+
+ review: {review.rating}/5 +
+
+
+ ))} +
+
+
Map
+ + {`Book ${title}`} + + + ); + } +}; + +ListingPageComponent.loadData = (id, onLoadListing) => { + onLoadListing(id); +}; + +ListingPageComponent.defaultProps = { listing: null }; + +const { func, object, shape, string } = PropTypes; + +ListingPageComponent.propTypes = { + entitiesData: object.isRequired, + onLoadListing: func.isRequired, + params: shape({ + id: string.isRequired, + slug: string.isRequired, + }).isRequired, +}; + +const mapStateToProps = state => { + const { data, ListingPage } = state; + const entitiesData = data ? data : {}; + return { ListingPage, entitiesData }; +}; + +const mapDispatchToProps = (dispatch) => { + return { + onLoadListing: (id) => dispatch(showListings({ id, include: ['author'] })), + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ListingPageComponent);