diff --git a/src/components/ListingCard/images/noImageIcon.svg b/src/components/ListingCard/images/noImageIcon.svg
new file mode 100644
index 00000000..c168d5cd
--- /dev/null
+++ b/src/components/ListingCard/images/noImageIcon.svg
@@ -0,0 +1 @@
+
diff --git a/src/components/ListingCardSmall/ListingCardSmall.css b/src/components/ListingCardSmall/ListingCardSmall.css
index 4ac667ed..8d7527af 100644
--- a/src/components/ListingCardSmall/ListingCardSmall.css
+++ b/src/components/ListingCardSmall/ListingCardSmall.css
@@ -4,6 +4,8 @@
flex-direction: column;
border-radius: 4px;
margin-right: 1rem;
+ flex-basis: 130px;
+ flex-shrink: 0;
}
.squareWrapper {
@@ -14,9 +16,10 @@
/* Firefox doesn't support image aspect ratio inside flexbox */
.aspectWrapper {
- padding-bottom: 75%; /* 4:3 Aspect Ratio */
+ padding-bottom: 100%; /* 4:3 Aspect Ratio */
}
+.noImageContainer,
.thumbnail {
position: absolute;
top: 0;
@@ -26,6 +29,18 @@
width: 100%;
height: 100%;
}
+.noImageContainer,
+.noImageWrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ background-color: #eee;
+}
+
+.noImageText {
+ color: #666;
+}
.info {
width: 100%;
diff --git a/src/components/ListingCardSmall/ListingCardSmall.js b/src/components/ListingCardSmall/ListingCardSmall.js
index 4c08e8ae..940013f8 100644
--- a/src/components/ListingCardSmall/ListingCardSmall.js
+++ b/src/components/ListingCardSmall/ListingCardSmall.js
@@ -2,6 +2,7 @@ import React from 'react';
import { NamedLink } from '../../components';
import * as propTypes from '../../util/propTypes';
import css from './ListingCardSmall.css';
+import noImageIcon from './images/noImageIcon.svg';
const ListingCardSmall = props => {
const { listing } = props;
@@ -13,12 +14,39 @@ const ListingCardSmall = props => {
// to do with them
const price = '55\u20AC / day';
const review = { rating: 3, count: 10 };
+ const images = listing.images
+ ? listing.images.map(i => ({ id: i.id, sizes: i.attributes.sizes }))
+ : [];
+ const mainImage = images.length > 0 ? images[0] : null;
+ const squareImageURL = mainImage ? mainImage.sizes.find(i => i.name === 'square').url : null;
+ const square2XImageURL = mainImage
+ ? mainImage.sizes.find(i => i.name === 'square2x').url
+ : null;
+ const higherRes = square2XImageURL ? { srcSet: `${square2XImageURL} 2x` } : null;
+
+ // TODO: svg should have own loading strategy
+ // Now noImageIcon is imported with default configuration (gives url)
+ /* eslint-disable jsx-a11y/img-redundant-alt */
+ const noListingImage = (
+
+
+

+
No image
+
+
+ );
+ /* eslint-enable jsx-a11y/img-redundant-alt */
+ const listingImage = (
+

+ );
+
+ const imageOrPlaceholder = squareImageURL ? listingImage : noListingImage;
return (
-

+ {imageOrPlaceholder}
diff --git a/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap b/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap
index c89265a6..1de934e6 100644
--- a/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap
+++ b/src/components/ListingCardSmall/__snapshots__/ListingCardSmall.test.js.snap
@@ -2,9 +2,16 @@ exports[`ListingCardSmall matches snapshot 1`] = `
-

+
+
+

+
+ No image
+
+
+
diff --git a/src/components/ListingCardSmall/images/noImageIcon.svg b/src/components/ListingCardSmall/images/noImageIcon.svg
new file mode 100644
index 00000000..c168d5cd
--- /dev/null
+++ b/src/components/ListingCardSmall/images/noImageIcon.svg
@@ -0,0 +1 @@
+
diff --git a/src/components/MapPanel/MapPanel.css b/src/components/MapPanel/MapPanel.css
index 3ff8f8e6..01812a91 100644
--- a/src/components/MapPanel/MapPanel.css
+++ b/src/components/MapPanel/MapPanel.css
@@ -1,5 +1,5 @@
.mapContainer {
- height: 70vh;
+ height: calc(100vh - 237px);
width: 100%;
display: flex;
align-items: center;
@@ -9,8 +9,9 @@
font-size: 2rem;
}
.mapListingsContainer {
- height: 30vh;
- width: 100%;
+ height: 237px;
+ width: auto;
+ overflow-x: scroll;
background-color: #fff;
display: flex;
flex-direction: row;
diff --git a/src/containers/EditListingForm/EditListingForm.test.js b/src/containers/EditListingForm/EditListingForm.test.js
index 23e56029..5ed55006 100644
--- a/src/containers/EditListingForm/EditListingForm.test.js
+++ b/src/containers/EditListingForm/EditListingForm.test.js
@@ -8,7 +8,14 @@ import EditListingForm from './EditListingForm';
describe('EditListingForm', () => {
it('matches snapshot', () => {
- const tree = renderShallow(
v} onSubmit={v => v} onUpdateImageOrder={v => v} />);
+ const tree = renderShallow(
+ v}
+ onSubmit={v => v}
+ onUpdateImageOrder={v => v}
+ />,
+ );
expect(tree).toMatchSnapshot();
});
});
diff --git a/src/containers/SearchPage/SearchPage.js b/src/containers/SearchPage/SearchPage.js
index 51c2463d..95c28f0d 100644
--- a/src/containers/SearchPage/SearchPage.js
+++ b/src/containers/SearchPage/SearchPage.js
@@ -51,7 +51,7 @@ export class SearchPageComponent extends Component {
}
SearchPageComponent.loadData = dispatch => {
- dispatch(searchListings({ origin: new LatLng(40, 70), include: ['author'] }));
+ dispatch(searchListings({ origin: new LatLng(40, 70), include: ['author', 'images'] }));
};
SearchPageComponent.defaultProps = { initialListingsLoaded: false, listings: [], tab: 'listings' };
diff --git a/src/util/propTypes.js b/src/util/propTypes.js
index 688f8b93..5a180601 100644
--- a/src/util/propTypes.js
+++ b/src/util/propTypes.js
@@ -21,7 +21,7 @@ import { PropTypes } from 'react';
import { types as sdkTypes } from 'sharetribe-sdk';
const { UUID, LatLng, LatLngBounds } = sdkTypes;
-const { oneOf, string, bool, func, shape, instanceOf } = PropTypes;
+const { arrayOf, bool, func, instanceOf, number, oneOf, shape, string } = PropTypes;
// Fixed value
export const value = val => oneOf([val]);
@@ -62,6 +62,20 @@ export const user = shape({
}),
});
+// Denormalised image object
+export const image = shape({
+ id: uuid.isRequired,
+ type: value('image').isRequired,
+ attributes: shape({
+ sizes: arrayOf(shape({
+ width: number.isRequired,
+ height: number.isRequired,
+ name: string.isRequired,
+ url: string.isRequired,
+ })).isRequired,
+ }),
+});
+
// Denormalised listing object
export const listing = shape({
id: uuid.isRequired,
@@ -73,4 +87,5 @@ export const listing = shape({
geolocation: latlng.isRequired,
}),
author: user,
+ images: arrayOf(image),
});