Files
old-kivi/web/components/Main.js
2017-04-06 01:12:06 +02:00

374 lines
9.0 KiB
JavaScript

import React from 'react';
import Filters from './Filters';
import Listings from './Listings';
import ListingDetails from './ListingDetails';
import { pacSelectFirst } from '../helpers/googleMaps';
import {loadProperties} from '../lib/api'
import {handleMessage} from '../lib/handlers'
class Main extends React.Component {
constructor(props) {
super(props);
this.state = {
listingDetails: false,
listings: (new Map()),
imageIndex: 0,
filters: {
rooms: {},
category: {}
}
};
}
dispatch ({type, action = {}}) {
handleMessage({type, action}, this);
}
componentDidMount() {
const uluru = {lat: 43.845031, lng: 18.4019262};
const map = new google.maps.Map(this.refs.map, {
zoom: 13,
center: uluru,
streetViewControl: false,
mapTypeControl: false
});
//const marker = new google.maps.Marker({
//position: uluru,
//map: map
//});
var control = document.createElement('div');
control.classList.add('filters-btn-toggle');
control.innerHTML = '<button>Filters</button>';
//control.style = "top: 200px;"
control["style"]= "top: 200px;"
var input = document.getElementById('gmaps-places-input');
pacSelectFirst(input);
var options = {
componentRestrictions: {country: "BA"}
};
var searchBox = new google.maps.places.Autocomplete(input, options);
searchBox.addListener('place_changed', () => {
var place = searchBox.getPlace();
if (!place.geometry) {
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(18);
}
console.log(map.getBounds());
this.dispatch({type: 'SEARCH_PLACE_CHANGED'});
});
control.addEventListener('click', (e) => {
this.setState({
mapClicked: true
});
});
control.index = 1;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(control);
this.map = map;
map.addListener('zoom_changed', () => {
console.log('zoom_changed');
this.removeAllMarkers();
this.markers = [];
});
map.addListener('idle', () => {
console.log('idle');
this.refreshListings();
});
}
removeAllMarkers () {
if (this.markers) {
console.log('removeAllMarkers');
this.markers.forEach((m) => m.marker.setMap(null));
}
}
onCloseClick(e) {
if (this.state.mapClicked) {
setTimeout(() => {
google.maps.event.trigger(this.map, 'resize');
}, 100);
}
this.setState({
mapClicked: false
});
}
findMarker (id) {
if (!this.markers) {
return null;
}
const index = this.markers.findIndex(m => m.id === id);
return this.markers[index];
}
/*
* Refreshes search
*/
refreshListings() {
console.log('refreshListings');
const map = this.map;
const {
rooms,
minSize,
maxSize,
minPrice,
maxPrice,
category
} = this.state.filters;
const bounds = map.getBounds();
const properties = loadProperties({
bounds: bounds.toUrlValue(),
rooms,
minSize,
maxSize,
minPrice,
maxPrice,
category
});
const markerExists = (id) => {
return this.findMarker(id) != null;
}
properties.then(p => p.text()).then(p => {
const data = JSON.parse(p);
console.log('results_received');
const listingExists = (id) => {
return data.findIndex(l => l._id === id) !== -1
};
const newMarkers = [];
if (this.markers) {
this.markers.forEach((m) => {
if (!listingExists(m.id)) {
m.marker.setMap(null);
} else {
newMarkers.push(m);
}
});
console.log('markers_removed');
}
for(const [index, prop] of data.entries()) {
const myLatLng = {lat: prop.loc[0], lng: prop.loc[1]};
if (!markerExists(prop._id)) {
const marker = new google.maps.Marker({
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...', 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._id
}});
});
newMarkers.push({
marker,
id: prop._id
});
}
}
this.dispatch({
type: 'LISTINGS_LOADED',
action: {
listings: data,
newMarkers
}
});
})
}
onListingClick() {
this.setState({
listingDetails: true
})
}
onBackClick() {
this.setState({
listingDetails: false
})
}
/*
* 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 = [];
if (this.state.listingDetails) {
console.log('CURRENT LISTINGS', this.state.listings);
const listing = this.state.listings.get(this.state.listingId);
console.log(this.state);
children.push(<ListingDetails
listing={listing}
imageIndex={this.state.imageIndex}
dispatch={this.dispatch.bind(this)}
descriptionExpanded={this.state.descriptionExpanded}
onBackClick={this.onBackClick.bind(this)}/>);
} else {
children.push(<Filters filters={this.state.filters} dispatch={this.dispatch.bind(this)} onClose={this.onCloseClick.bind(this)}/>);
children.push(<Listings
listings={this.state.listings}
dispatch={this.dispatch.bind(this)}
onListingClick={this.onListingClick.bind(this)}/>);
}
const content = (
<div className="right-content">
{children}
</div>);
return content;
}
render() {
const leftStyle = {};
const rightStyle = {};
const listingDetails = true;
let leftClass = 'left-base';
let rightClass = 'right-base';
if (this.state.mapClicked) {
leftClass = 'left-hidden';
rightClass = 'right-shown';
}
return (
<div id="container">
<div id="header">
<a className="hamburger-menu">K</a>
<span className="title">Kiwi</span>
<input
id="gmaps-places-input"
placeholder="Unesite adresu, naselje ili grad"
className="where-to"
type="text"></input>
<div className="view-types">
<a className="view-type-left">
<i className="btn-select-map fa fa-list"></i>
</a>
<a className="view-type-right">
<i className="view-type-map-icon fa fa-map-marker"></i>
</a>
</div>
</div>
<div id="right" style={rightStyle} className={rightClass}>
{this.renderRightContent()}
</div>
<div id="left" style={leftStyle} className={leftClass}>
<div id="map" ref="map">
</div>
</div>
</div>
)
}
}
export default Main;