diff --git a/backend/build/server.js b/backend/build/server.js index 44f22d0..ffc23dc 100644 --- a/backend/build/server.js +++ b/backend/build/server.js @@ -74,7 +74,7 @@ router.get('/search', function () { var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(req, res, next) { - var bounds, minPrice, maxPrice, minSize, maxSize, rooms, adType, category, sort, properties, query, _bounds$split$map, _bounds$split$map2, lat1, lng1, lat2, lng2, box, price, allRooms, or, size, allCategories, _or, all; + var bounds, minPrice, maxPrice, minSize, maxSize, rooms, adType, category, sort, properties, query, _bounds$split$map, _bounds$split$map2, lat1, lng1, lat2, lng2, box, price, and, allRooms, or, size, allCategories, _or, all; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { @@ -130,6 +130,8 @@ }); } + and = []; + if (rooms) { allRooms = rooms.split(','); or = allRooms.map(function (val) { @@ -146,9 +148,10 @@ }); - query = Object.assign(query, { - "$or": or - }); + and.push({ "$or": or }); + //query = Object.assign(query, { + //rooms: + //}); } if (minSize || maxSize) { @@ -176,40 +179,47 @@ }); + and.push({ "$or": _or }); + //query = Object.assign(query, { + //{"$or" : or } + //}); + } + + if (and.length > 0) { query = Object.assign(query, { - "$or": _or + "$and": and }); } console.log('QUERY: ', query); - _context.next = 21; + _context.next = 23; return properties.find(query, { //"sort": [['field1','asc'], ['field2','desc']] "sort": [['price', 'asc']] }).toArray(); - case 21: + case 23: all = _context.sent; res.json(all); res.end(); - _context.next = 30; + _context.next = 32; break; - case 26: - _context.prev = 26; + case 28: + _context.prev = 28; _context.t0 = _context['catch'](0); console.log('error:', _context.t0); next(_context.t0); - case 30: + case 32: case 'end': return _context.stop(); } } - }, _callee, undefined, [[0, 26]]); + }, _callee, undefined, [[0, 28]]); })); return function (_x, _x2, _x3) { diff --git a/backend/server.js b/backend/server.js index a393ded..82e987f 100644 --- a/backend/server.js +++ b/backend/server.js @@ -60,6 +60,7 @@ router.get('/search', async (req, res, next) => { }); } + const and = []; if (rooms) { const allRooms = rooms.split(','); const or = allRooms.map(val => { @@ -75,9 +76,7 @@ router.get('/search', async (req, res, next) => { }; }); - query = Object.assign(query, { - "$or": or - }); + and.push({ "$or": or }); } if (minSize || maxSize) { @@ -103,8 +102,12 @@ router.get('/search', async (req, res, next) => { }; }); + and.push({ "$or": or }); + } + + if (and.length > 0) { query = Object.assign(query, { - "$or": or + "$and": and }); } diff --git a/web/components/Listings.js b/web/components/Listings.js index f69969f..88bde65 100644 --- a/web/components/Listings.js +++ b/web/components/Listings.js @@ -11,6 +11,15 @@ export default class Listings extends React.Component { }); } + onMouseEnter (id) { + this.props.dispatch({ + type: 'ON_LISTING_MOUSE_OVER', + action: { + id + } + }); + } + renderListings () { const {listings = (new Map())} = this.props; @@ -22,8 +31,9 @@ export default class Listings extends React.Component { rendered.push(
+ onClick={this.onListingClick.bind(this, l._id)}>
diff --git a/web/components/Main.js b/web/components/Main.js index ecf73f5..9b01f5a 100644 --- a/web/components/Main.js +++ b/web/components/Main.js @@ -112,6 +112,15 @@ class Main extends React.Component { }); } + findMarker (id) { + if (!this.markers) { + return null; + } + + const index = this.markers.findIndex(m => m.id === id); + return this.markers[index]; + } + /* * Refreshes search */ @@ -138,8 +147,9 @@ class Main extends React.Component { category }); + const markerExists = (id) => { - return (this.markers || []).findIndex(m => m.id === id) !== -1; + return this.findMarker(id) != null; } properties.then(p => p.text()).then(p => { @@ -168,18 +178,42 @@ class Main extends React.Component { for(const [index, prop] of data.entries()) { const myLatLng = {lat: prop.loc[0], lng: prop.loc[1]}; - if (!markerExists(p._id)) { + if (!markerExists(prop._id)) { + const marker = new google.maps.Marker({ - position: myLatLng, - map: map, - title: prop.title + position : myLatLng, + map : map, + title : prop.title, + icon : this.defaultMarkerIcon(), + id : prop._id + }); + + marker.addListener('mouseover', () => { + if (marker.id !== this.state.listingId) { + marker.setIcon(this.hoveredMarkerIcon()); + } + }); + + marker.addListener('mouseout', () => { + if (marker.id !== this.state.listingId) { + marker.setIcon(this.defaultMarkerIcon()); + } }); marker.addListener('click', () => { - console.log('clicking...') + console.log('clicking...', prop._id); + if (this.state.listingId) { + const prevSelected = this.findMarker(this.state.listingId); + if (prevSelected) { + console.log('prevselected', prevSelected); + prevSelected.marker.setIcon(this.defaultMarkerIcon()); + } + } + + marker.setIcon(this.selectedMarkerIcon()); this.dispatch({type: 'VIEW_LISTING_DETAILS', action: { - id: prop.url - }}) + id: prop._id + }}); }); newMarkers.push({ @@ -211,6 +245,57 @@ class Main extends React.Component { }) } + /* + * Get default marker icon + */ + defaultMarkerIcon () { + const sf = 0.5; + const width = 48; + const height = 64; + const icon = { + url : "static/images/pins_sprite.png", + size : new google.maps.Size(width * sf, height * sf), + scaledSize : new google.maps.Size(730 * sf, 102 * sf), + origin : new google.maps.Point(0, 36 * sf) + } + + return icon; + } + + /* + * Hovered marker icon + */ + hoveredMarkerIcon () { + const sf = 0.5; + const width = 61; + const height = 82; + const icon = { + url : "static/images/pins_sprite.png", + size : new google.maps.Size(width * sf, height * sf), + scaledSize : new google.maps.Size(730 * sf, 102 * sf), + origin : new google.maps.Point(303 * sf, 18 * sf) + } + + return icon; + } + + /* + * Selected marker icon + */ + selectedMarkerIcon () { + const sf = 0.5; + const width = 73; + const height = 100; + const icon = { + url : "static/images/pins_sprite.png", + size : new google.maps.Size(width * sf, height * sf), + scaledSize : new google.maps.Size(730 * sf, 102 * sf), + origin : new google.maps.Point(655 * sf, 1 * sf) + } + + return icon; + } + renderRightContent() { const children = []; diff --git a/web/dist/static/images/pins_sprite.png b/web/dist/static/images/pins_sprite.png new file mode 100644 index 0000000..6533948 Binary files /dev/null and b/web/dist/static/images/pins_sprite.png differ diff --git a/web/lib/handlers.js b/web/lib/handlers.js index db6ce87..7b2c13d 100644 --- a/web/lib/handlers.js +++ b/web/lib/handlers.js @@ -55,7 +55,7 @@ const listingsLoaded = ({ type, action }, component) => { const currentListings = new Map(); for (const listing of action.listings) { - currentListings.set(listing.url, listing); + currentListings.set(listing._id, listing); } component.setState({ @@ -151,7 +151,20 @@ const setCategory = ({type, action}, component) => { component.refreshListings(); } ); -} +}; + +const onListingMouseOver = ({type, action}, component) => { + const marker = component.findMarker(action.id); + if (marker) { + marker.marker.setIcon(component.hoveredMarkerIcon()); + marker.marker.setAnimation(google.maps.Animation.BOUNCE); + setTimeout(() => { + marker.marker.setAnimation(null); + marker.marker.setIcon(component.defaultMarkerIcon()); + } , 710); + } + +}; const handlers = { SET_MIN_PRICE: setMinPrice, @@ -167,7 +180,8 @@ const handlers = { SET_ROOMS: setRooms, VIEW_LISTING_DETAILS: viewListingDetails, UPDATE_SEARCH: updateSearch, - SET_CATEGORY: setCategory + SET_CATEGORY: setCategory, + ON_LISTING_MOUSE_OVER: onListingMouseOver }; export const handleMessage = ({ type, action }, component) => {