Reorganize & reformat

This commit is contained in:
Edin Dazdarevic
2017-04-11 10:43:05 +02:00
parent a1151150db
commit 4a8740fb35
22 changed files with 2364 additions and 1353 deletions

View File

@@ -0,0 +1,256 @@
import React from 'react'
import {formatFilterNumber} from '../lib/helpers'
import {
CATEGORY_FLAT,
CATEGORY_HOUSE,
CATEGORY_OFFICE,
CATEGORY_LAND
} from '../../../crawler/enums'
export default class Filters extends React.Component {
onCloseClick (e) {
if (this.props.onClose) {
this.props.onClose()
}
}
onMaxPriceChange (e) {
const maxPrice = e.target.value
this.props.dispatch({
type: 'SET_MAX_PRICE',
action: {maxPrice}
})
}
onMinPriceChange (e) {
const minPrice = e.target.value
this.props.dispatch({
type: 'SET_MIN_PRICE',
action: {minPrice}
})
}
onMaxSizeChange (e) {
this.props.dispatch({
type: 'SET_MAX_SIZE',
action: {maxSize: e.target.value}
})
}
onMinSizeChange (e) {
this.props.dispatch({
type: 'SET_MIN_SIZE',
action: {minSize: e.target.value}
})
}
onRoomsClick (rooms) {
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
params: {rooms}
}
})
this.props.dispatch({type: 'SET_ROOMS', action: {rooms}})
}
onCategoryClick (category) {
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
params: {category}
}
})
this.props.dispatch({type: 'SET_CATEGORY', action: {category}})
}
onRefreshClick () {
this.updateSearch()
}
onKeyPress (e) {
if (e.key === 'Enter') {
this.updateSearch()
}
}
updateSearch () {
const {minPrice, maxPrice, minSize, maxSize} = this.props.filters
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
params: {
minPrice,
maxPrice,
minSize,
maxSize
}
}
})
this.props.dispatch({type: 'UPDATE_SEARCH'})
}
render () {
const {filters} = this.props
const selectedRooms = val => filters.rooms[val] ? 'selected' : ''
const selectedCategory = val => filters.category[val] ? 'selected' : ''
return (
<div className="filters">
<div className="filters-close">
Uslovi Pretrage
<i
onClick={this.onCloseClick.bind(this)}
className="close-icon fa fa-times"
aria-hidden="true"
/>
</div>
<div className="filter-row">
<div className="filter-title">
CIJENA
</div>
<div className="filter-content value-between-box">
OD
<input
onKeyPress={this.onKeyPress.bind(this)}
onChange={this.onMinPriceChange.bind(this)}
value={formatFilterNumber(filters.minPrice)}
/>
{' '}
DO
<input
onKeyPress={this.onKeyPress.bind(this)}
onChange={this.onMaxPriceChange.bind(this)}
value={formatFilterNumber(filters.maxPrice)}
/>
{this.props.filters.priceDirty
? <i
onClick={this.onRefreshClick.bind(this)}
className="fa fa-refresh fa-refresh-custom"
aria-hidden="true"
/>
: null}
</div>
</div>
<div className="filter-row filter-property-types">
<div className="filter-title">
TIP
</div>
<div className="filter-content">
<div
onClick={this.onCategoryClick.bind(this, CATEGORY_FLAT)}
className={
`filter-btn property-type-btn ${selectedCategory(CATEGORY_FLAT)}`
}
>
Stan
</div>
<div
onClick={this.onCategoryClick.bind(this, CATEGORY_HOUSE)}
className={
`filter-btn property-type-btn ${selectedCategory(CATEGORY_HOUSE)}`
}
>
Kuća
</div>
</div>
<div className="filter-content">
<div
onClick={this.onCategoryClick.bind(this, CATEGORY_LAND)}
className={
`filter-btn property-type-btn ${selectedCategory(CATEGORY_LAND)}`
}
>
Zemljište
</div>
<div
onClick={this.onCategoryClick.bind(this, CATEGORY_OFFICE)}
className={
`filter-btn property-type-btn ${selectedCategory(CATEGORY_OFFICE)}`
}
>
Poslovni prostor
</div>
</div>
</div>
<div className="filter-row">
<div className="filter-title">
KVADRATA
</div>
<div className="filter-content value-between-box">
OD
<input
onKeyPress={this.onKeyPress.bind(this)}
value={formatFilterNumber(filters.minSize)}
onChange={this.onMinSizeChange.bind(this)}
/>
DO
{' '}
<input
onKeyPress={this.onKeyPress.bind(this)}
value={formatFilterNumber(filters.maxSize)}
onChange={this.onMaxSizeChange.bind(this)}
/>
{this.props.filters.sizeDirty
? <i
onClick={this.onRefreshClick.bind(this)}
className="fa fa-refresh fa-refresh-custom"
aria-hidden="true"
/>
: null}
</div>
</div>
<div className="filter-row filter-property-rooms no-border">
<div className="filter-title">
BROJ SOBA
</div>
<div className="filter-content">
<div
onClick={this.onRoomsClick.bind(this, 0)}
className={
`filter-btn property-rooms-studio-btn ${selectedRooms(0)}`
}
>
Garsonjera
</div>
<div
onClick={this.onRoomsClick.bind(this, 2)}
className={`filter-btn property-rooms-btn ${selectedRooms(2)}`}
>
2
</div>
<div
onClick={this.onRoomsClick.bind(this, 3)}
className={`filter-btn property-rooms-btn ${selectedRooms(3)}`}
>
3
</div>
<div
onClick={this.onRoomsClick.bind(this, '4+')}
className={`filter-btn property-rooms-btn ${selectedRooms('4+')}`}
>
4+
</div>
</div>
</div>
<div className="filter-row no-border">
<div className="filter-title" />
<div className="filter-content">
<div className="hide filter-btn more-filters">Više Filtera</div>
</div>
</div>
<div className="clear-both" />
<div className="filter-bottom" />
</div>
)
}
}

View File

@@ -0,0 +1,87 @@
import React from 'react'
import {galleryImageUrl} from '../lib/helpers'
export default class Gallery extends React.Component {
onPrevClick (e) {
this.props.dispatch({type: 'PREV_IMAGE'})
}
onNextClick (e) {
this.props.dispatch({type: 'NEXT_IMAGE'})
}
onImageDotClick (index, e) {
this.props.dispatch({type: 'VIEW_IMAGE', action: {index}})
}
render () {
const {images, imageIndex} = this.props
if (!images || images.length === 0) {
return null
}
const showPrev = imageIndex > 0
const showNext = imageIndex < images.length - 1
return (
<div className="ld-image-container">
<img src={galleryImageUrl(images[imageIndex])} />
{showPrev
? <div className="prev-button" onClick={this.onPrevClick.bind(this)}>
<div>
<svg
fill="white"
version="1.1"
x="0px"
y="0px"
width="100%"
height="100%"
viewBox="0 0 512 512"
>
<path
d="M213.7,256L213.7,256L213.7,256L380.9,81.9c4.2-4.3,4.1-11.4-0.2-15.8l-29.9-30.6c-4.3-4.4-11.3-4.5-15.5-0.2L131.1,247.9 c-2.2,2.2-3.2,5.2-3,8.1c-0.1,3,0.9,5.9,3,8.1l204.2,212.7c4.2,4.3,11.2,4.2,15.5-0.2l29.9-30.6c4.3-4.4,4.4-11.5,0.2-15.8 L213.7,256z"
/>
</svg>
</div>
</div>
: null}
{showNext
? <div className="next-button" onClick={this.onNextClick.bind(this)}>
<div>
<svg
fill="white"
version="1.1"
x="0px"
y="0px"
width="100%"
height="100%"
viewBox="0 0 512 512"
>
<path
d="M298.3,256L298.3,256L298.3,256L131.1,81.9c-4.2-4.3-4.1-11.4,0.2-15.8l29.9-30.6c4.3-4.4,11.3-4.5,15.5-0.2l204.2,212.7 c2.2,2.2,3.2,5.2,3,8.1c0.1,3-0.9,5.9-3,8.1L176.7,476.8c-4.2,4.3-11.2,4.2-15.5-0.2L131.3,446c-4.3-4.4-4.4-11.5-0.2-15.8 L298.3,256z"
/>
</svg>
</div>
</div>
: null}
<div className="image-dots">
{images.map((img, index) => {
let cls = 'image-dot'
if (index === imageIndex) {
cls += ' selected'
}
return (
<div
key={img}
onClick={this.onImageDotClick.bind(this, index)}
className={cls}
/>
)
})}
</div>
</div>
)
}
}

View File

@@ -0,0 +1,114 @@
import React from 'react'
import Gallery from './gallery'
import {formatPrice} from '../lib/helpers'
export default class ListingDetails extends React.Component {
onReadMore (e) {
e.preventDefault()
this.props.dispatch({type: 'EXPAND_DESCRIPTION'})
}
onBackClick () {
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
toDispatch: {
type: 'BACK_TO_RESULTS'
},
params: {
listingId: null
}
}
})
this.props.dispatch({type: 'BACK_TO_RESULTS'})
}
render () {
const {listing, descriptionExpanded} = this.props
if (!listing) {
return null
}
const descriptionClasses = descriptionExpanded
? 'ld-description expanded'
: 'ld-description'
const images = listing.images.map(image => ({
original: image,
thumbnail: image
}))
return (
<div className="ld-container">
<div className="ld-header">
<div className="back-to-results">
<button
className="back-to-results-btn"
onClick={this.onBackClick.bind(this)}
>
<i className="fa fa-arrow-left" aria-hidden="true" />
<span>
Nazad na rezultate
</span>
</button>
</div>
<button className="hide-listing">
<i className="fa fa-thumbs-o-down" aria-hidden="true" />
<span>
Sakrij
</span>
</button>
</div>
<div className="ld-details">
<Gallery
dispatch={this.props.dispatch}
images={listing.images}
imageIndex={this.props.imageIndex}
/>
<div className="ld-price-address-box">
<div className="ld-price">
{formatPrice(listing.price)}
</div>
<div className="ld-address">
<div className="">{listing.address}</div>
<div className="">{listing.location}</div>
</div>
</div>
<div className="ld-features">
<div className="ld-feature-box">
<i className="fa fa-bed" />
{listing.rooms} sobe
</div>
<div className="ld-feature-box">
<i className="fa fa-home" />
{listing.size}m2
</div>
<div className="ld-feature-box">
<i className="fa fa-home" />
{listing.floor}. sprat
</div>
<div className="ld-feature-box">
<i className="fa fa-home" />
--
</div>
</div>
<div className="ld-check-availability">
<button>Kontaktiraj</button>
</div>
<div className={descriptionClasses}>
{listing.longDescription}
</div>
{!descriptionExpanded
? <div className="ld-read-more">
<a href="" onClick={this.onReadMore.bind(this)}>
Pročitajte više
</a>
</div>
: null}
<div className="ld-footer" />
</div>
</div>
)
}
}

View File

@@ -0,0 +1,183 @@
import React from 'react'
import {findDOMNode} from 'react-dom'
import {formatPrice, listingImageUrl} from '../lib/helpers'
import {loadListing} from '../lib/api'
export default class Listings extends React.Component {
constructor (props) {
super(props)
this.handleScroll = e => {
const node = e.target
const offset = node.scrollHeight - node.scrollTop - node.clientHeight
if (this.props && this.props.loadingMore) {
return
}
if (offset < 50) {
this.props.dispatch({type: 'LOAD_MORE_LISTINGS'})
}
}
}
onListingClick (id) {
loadListing(id).then(l => l.text()).then(l => {
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
toDispatch: {
type: 'VIEW_LISTING_DETAILS',
action: {
id,
listing: JSON.parse(l)
}
},
params: {
listingId: id
}
}
})
this.props.dispatch({
type: 'VIEW_LISTING_DETAILS',
action: {
id,
listing: JSON.parse(l)
}
})
})
}
onMouseEnter (id) {
this.props.dispatch({
type: 'ON_LISTING_MOUSE_OVER',
action: {
id
}
})
}
renderListings () {
const {listings = new Map()} = this.props
if (listings.size === 0) {
return (
<div className="listings-no-results">
<i className="fa fa-frown-o fa-frown-o-custom" aria-hidden="true" />
<h4>Nema rezultata</h4>
<h5>
Nema oglasa koji ispunjavaju vaše uslove pretrage.
</h5>
</div>
)
}
const rendered = []
for (const l of listings.values()) {
const {images} = l
rendered.push(
<div
key={l._id}
onMouseEnter={this.onMouseEnter.bind(this, l._id)}
className="property-list-item"
onClick={this.onListingClick.bind(this, l._id)}
>
<div className="pli-image">
<img src={listingImageUrl(images[0])} alt="" />
</div>
<div className="pli-details">
<div className="price">{formatPrice(l.price)}</div>
<div className="description">
{l.rooms ? `${l.rooms} sobe, ` : null}
{l.size ? `${l.size}m2` : null}
</div>
<div className="address">
<div className="street">
{l.address}
</div>
<div className="location">
{l.location}
</div>
</div>
<div className="hours-ago">Prije {l.time}</div>
</div>
</div>
)
}
return rendered
}
componentDidMount () {
this.attachScrollListener()
}
componentWillUnmount () {
this.removeScrollListener()
}
attachScrollListener () {
const listings = findDOMNode(this.refs.listings)
listings.parentNode.addEventListener('scroll', this.handleScroll)
}
removeScrollListener () {
const listings = findDOMNode(this.refs.listings)
listings.parentNode.removeEventListener('scroll', this.handleScroll)
}
onSortChange (e) {
this.props.dispatch({
type: 'UPDATE_ROUTE',
action: {
params: {
sort: e.target.value
}
}
})
this.props.dispatch({
type: 'SORT_CHANGE',
action: {
sort: e.target.value
}
})
}
render () {
const {listings = new Map(), totalCount, sort} = this.props
return (
<div ref="listings" className="listings">
<div className="listings-header">
<div className="select-container">
<div className="select-group">
<select
value={sort}
onChange={this.onSortChange.bind(this)}
name="listings-type"
id="listings-type"
>
<option value="relevance">Relevantno</option>
<option value="newest">Najnovije</option>
<option value="price-min">Cijena: od najmanje</option>
<option value="price-max">Cijena: od najvece</option>
</select>
</div>
</div>
<div className="listings-count">
{totalCount} rezultata
</div>
</div>
<div className="listings-items">
{this.renderListings()}
</div>
</div>
)
}
}

592
web/src/components/Main.js Normal file
View File

@@ -0,0 +1,592 @@
import React from 'react'
import Filters from './Filters'
import Listings from './Listings'
import ListingDetails from './ListingDetails'
import {pacSelectFirst} from '../helpers/googleMaps'
import {loadProperties, loadSeen, loadListing} from '../lib/api'
import {handleMessage} from '../lib/handlers'
import Router from '../lib/router'
class Main extends React.Component {
constructor (props) {
super(props)
const state = {
listingDetails: false,
listings: new Map(),
imageIndex: 0,
page: 0,
sort: 'relevance',
filters: {
rooms: {},
category: {}
}
}
if (props.initialState) {
props.initialState.sort = props.initialState.sort || state.sort
state.filters.rooms = props.initialState.rooms
state.filters.category = props.initialState.category
state.sort = props.initialState.sort || state.sort
state.listingId = props.initialState.listingId
state.bounds = props.initialState.bounds
state.zoom = props.initialState.zoom
if (state.listingId) {
state.listingDetails = true
}
state.filters.minSize = props.initialState.minSize
state.filters.maxSize = props.initialState.maxSize
state.filters.minPrice = props.initialState.minPrice
state.filters.maxPrice = props.initialState.maxPrice
}
this.state = state
this.router = new Router(this, props.initialState)
}
dispatch ({type, action = {}}) {
handleMessage({type, action}, this)
}
componentDidMount () {
const uluru = {lat: 43.845031, lng: 18.4019262}
const opts = {
//zoom: 13,
//center: uluru,
streetViewControl: false,
mapTypeControl: false
}
if (!this.state.bounds) {
opts.zoom = 13
opts.center = uluru
}
const map = new google.maps.Map(this.refs.map, opts)
window.gmap = map
//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'}
}
const regularIdle = () => {
this.dispatch({
type: 'UPDATE_ROUTE',
action: {
params: {
bounds: map.getBounds().toUrlValue(),
zoom: map.getZoom()
}
}
})
this.dispatch({type: 'MAP_IDLE'})
}
// Check if initial bounds are passed-in
google.maps.event.addListenerOnce(map, 'idle', () => {
if (this.state.bounds) {
const [lat1, lng1, lat2, lng2] = this.state.bounds.split(',')
const sw = new google.maps.LatLng({
lat: parseFloat(lat1),
lng: parseFloat(lng1)
})
const ne = new google.maps.LatLng({
lat: parseFloat(lat2),
lng: parseFloat(lng2)
})
const initialBounds = new google.maps.LatLngBounds(sw, ne)
//map.fitBounds(initialBounds);
const originalMaxZoom = map.maxZoom
const originalMinZoom = map.minZoom
map.setOptions({
maxZoom: parseInt(this.state.zoom),
minZoom: parseInt(this.state.zoom)
})
map.fitBounds(initialBounds)
map.setOptions({maxZoom: originalMaxZoom, minZoom: originalMinZoom})
}
})
map.addListener('idle', regularIdle)
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)
}
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
// TODO: if state contains listingId reload
if (this.state.listingId) {
loadListing(this.state.listingId).then(l => l.text()).then(l => {
this.dispatch({
type: 'VIEW_LISTING_DETAILS',
action: {
id: this.state.listingId,
listing: JSON.parse(l)
}
})
})
}
}
removeAllMarkers () {
if (this.markers) {
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]
}
isSeen (id) {
const seen = loadSeen()
return seen.findIndex(s => s === id) !== -1
}
loadPins () {
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,
page: this.state.page,
pins: true
})
const markerExists = id => {
return this.findMarker(id) != null
}
properties
.then(p => {
return {
body: p.text(),
totalCount: p.headers.get('X-Total-Count')
}
})
.then(({body, totalCount}) => {
body.then(p => {
const data = JSON.parse(p)
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)
}
})
}
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.isSeen(prop._id)
? this.visitedMarkerIcon()
: this.defaultMarkerIcon(),
id: prop._id
})
marker.addListener('mouseover', () => {
if (marker.id !== this.state.listingId) {
if (this.isSeen(marker.id)) {
marker.setIcon(this.visitedHoveredMarkerIcon())
} else {
marker.setIcon(this.hoveredMarkerIcon())
}
}
})
marker.addListener('mouseout', () => {
if (marker.id !== this.state.listingId) {
if (this.isSeen(marker.id)) {
marker.setIcon(this.visitedMarkerIcon())
} else {
marker.setIcon(this.defaultMarkerIcon())
}
}
})
marker.addListener('click', () => {
// Maybe move out and call when popping state
if (this.state.listingId) {
const prevSelected = this.findMarker(this.state.listingId)
if (prevSelected) {
prevSelected.marker.setIcon(this.visitedMarkerIcon())
}
}
marker.setIcon(this.selectedMarkerIcon())
loadListing(prop._id).then(l => l.text()).then(l => {
this.dispatch({
type: 'UPDATE_ROUTE',
action: {
toDispatch: {
type: 'VIEW_LISTING_DETAILS',
action: {
id: prop._id,
listing: JSON.parse(l)
}
},
params: {
listingId: prop._id
}
}
})
//this.dispatch({type: 'UPDATE_ROUTE', action: {type: 'VIEW_LISTING_DETAILS', action: {
//id: prop._id,
//listing: JSON.parse(l)
//}}});
this.dispatch({
type: 'VIEW_LISTING_DETAILS',
action: {
id: prop._id,
listing: JSON.parse(l)
}
})
})
})
newMarkers.push({
marker,
id: prop._id
})
}
}
this.dispatch({
type: 'PINS_LOADED',
action: {
newMarkers
}
})
})
})
}
/*
* Refreshes search
*/
refreshListings (more = false) {
// TODO: move somewhere else
if (!more && this.state.listingId) {
loadListing(this.state.listingId).then(l => l.text()).then(l => {
this.dispatch({
type: 'VIEW_LISTING_DETAILS',
action: {
id: this.state.listingId,
listing: JSON.parse(l)
}
})
})
}
if (!more) {
this.loadPins()
}
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,
page: this.state.page,
sort: this.state.sort
})
properties
.then(p => {
return {
body: p.text(),
totalCount: p.headers.get('X-Total-Count')
}
})
.then(({body, totalCount}) => {
body.then(p => {
const data = JSON.parse(p)
this.dispatch({
type: 'LISTINGS_LOADED',
action: {
listings: data,
more,
totalCount
}
})
})
})
}
/*
* 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
}
/*
* Get visited marker icon
*/
visitedMarkerIcon () {
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(152 * sf, 36 * sf)
}
return icon
}
/*
* Visited hovered marker icon
*/
visitedHoveredMarkerIcon () {
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(480 * sf, 18 * 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) {
const listing = this.state.listing //this.state.listings.get(this.state.listingId);
children.push(
<ListingDetails
listing={listing}
imageIndex={this.state.imageIndex}
dispatch={this.dispatch.bind(this)}
descriptionExpanded={this.state.descriptionExpanded}
/>
)
} else {
children.push(
<Filters
filters={this.state.filters}
dispatch={this.dispatch.bind(this)}
onClose={this.onCloseClick.bind(this)}
/>
)
children.push(
<Listings
sort={this.state.sort}
totalCount={this.state.totalCount}
loadingMore={this.state.loadingMore}
listings={this.state.listings}
dispatch={this.dispatch.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"
/>
<div className="view-types">
<a className="view-type-left">
<i className="btn-select-map fa fa-list" />
</a>
<a className="view-type-right">
<i className="view-type-map-icon fa fa-map-marker" />
</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>
)
}
}
export default Main