Welcome page

This commit is contained in:
Edin Dazdarevic
2017-04-21 01:55:13 +02:00
parent 344877beda
commit 8f57f91d32
9 changed files with 290 additions and 112 deletions

View File

@@ -1,28 +1,27 @@
import React from 'react'
import {saveContactRequest} from '../lib/api'
import React from "react";
import { saveContactRequest } from "../lib/api";
export default class ContactModal extends React.Component {
onContactCloseClick (e) {
e.preventDefault()
onContactCloseClick(e) {
e.preventDefault();
this.props.dispatch({
type: 'CLOSE_CONTACT'
})
type: "CLOSE_CONTACT"
});
}
onSubmit (e) {
e.preventDefault()
const {name, email, message, phone, alert} = this.props.contact;
onSubmit(e) {
e.preventDefault();
const { name, email, message, phone, alert } = this.props.contact;
if (!name || !email) {
this.props.dispatch({
type: 'INVALID_CONTACT'
})
type: "INVALID_CONTACT"
});
} else {
this.props.dispatch({
type: 'SUBMIT_CONTACT_START'
})
type: "SUBMIT_CONTACT_START"
});
saveContactRequest(this.props.listingId, {
name,
@@ -30,39 +29,42 @@ export default class ContactModal extends React.Component {
phone,
message,
alert
}).then(l => l.text()).then(res => {
this.props.dispatch({
type: 'SUBMIT_CONTACT_END'
})
.then(l => l.text())
.then(res => {
this.props.dispatch({
type: "SUBMIT_CONTACT_END"
});
})
.catch(e => {
// TODO: should we have a global view for rendering errors
console.error(e);
});
}).catch(e => {
// TODO: should we have a global view for rendering errors
console.error(e)
});
}
}
onFieldChange (field, e) {
onFieldChange(field, e) {
this.props.dispatch({
type: 'UPDATE_CONTACT_INFO',
type: "UPDATE_CONTACT_INFO",
action: {
field,
value: e.target.value
}
})
});
}
onAlertToggle (e) {
const alert = this.props.contact.alert
onAlertToggle(e) {
const alert = this.props.contact.alert;
this.props.dispatch({
type: 'UPDATE_CONTACT_INFO',
type: "UPDATE_CONTACT_INFO",
action: {
field: 'alert',
field: "alert",
value: !alert
}
})
});
}
render () {
render() {
const {
message,
email,
@@ -72,10 +74,10 @@ export default class ContactModal extends React.Component {
nameInvalid,
emailInvalid,
sending
} = this.props.contact
} = this.props.contact;
const nameValidationClass = nameInvalid ? 'validation-failed' : ''
const emailValidationClass = emailInvalid ? 'validation-failed' : ''
const nameValidationClass = nameInvalid ? "validation-failed" : "";
const emailValidationClass = emailInvalid ? "validation-failed" : "";
return (
<div className="modal contact-form">
@@ -94,7 +96,7 @@ export default class ContactModal extends React.Component {
<input
value={name}
className={nameValidationClass}
onChange={this.onFieldChange.bind(this, 'name')}
onChange={this.onFieldChange.bind(this, "name")}
placeholder="Ime i prezime"
type="text"
/>
@@ -103,32 +105,32 @@ export default class ContactModal extends React.Component {
<input
value={email}
className={emailValidationClass}
onChange={this.onFieldChange.bind(this, 'email')}
onChange={this.onFieldChange.bind(this, "email")}
placeholder="Email adresa"
type="email"
name="email"
/>
<input
value={phone}
onChange={this.onFieldChange.bind(this, 'phone')}
onChange={this.onFieldChange.bind(this, "phone")}
placeholder="Telefon (opcionalno)"
type="text"
/>
</div>
<div className="contact-form-message">
<textarea
onChange={this.onFieldChange.bind(this, 'message')}
onChange={this.onFieldChange.bind(this, "message")}
value={message}
/>
</div>
<div className="contact-form-alert noselect">
<label>
<input
type="checkbox"
onChange={this.onAlertToggle.bind(this)}
checked={doAlert}
/>
Javi mi kada se objavi sličan oglas
<input
type="checkbox"
onChange={this.onAlertToggle.bind(this)}
checked={doAlert}
/>
Javi mi kada se objavi sličan oglas
</label>
</div>
<div className="contact-form-footer">
@@ -137,6 +139,6 @@ export default class ContactModal extends React.Component {
</form>
</div>
</div>
)
);
}
}

View File

@@ -1,94 +1,94 @@
import React from 'react'
import {formatFilterNumber} from '../lib/helpers'
import React from "react";
import { formatFilterNumber } from "../lib/helpers";
import {
CATEGORY_FLAT,
CATEGORY_HOUSE,
CATEGORY_OFFICE,
CATEGORY_LAND
} from '../../../crawler/enums'
} from "../../../crawler/enums";
export default class Filters extends React.Component {
onCloseClick (e) {
onCloseClick(e) {
if (this.props.onClose) {
this.props.onClose()
this.props.onClose();
}
}
onMaxPriceChange (e) {
const maxPrice = e.target.value
onMaxPriceChange(e) {
const maxPrice = e.target.value;
this.props.dispatch({
type: 'SET_MAX_PRICE',
action: {maxPrice}
})
type: "SET_MAX_PRICE",
action: { maxPrice }
});
}
onMinPriceChange (e) {
const minPrice = e.target.value
onMinPriceChange(e) {
const minPrice = e.target.value;
this.props.dispatch({
type: 'SET_MIN_PRICE',
action: {minPrice}
})
type: "SET_MIN_PRICE",
action: { minPrice }
});
}
onMaxSizeChange (e) {
onMaxSizeChange(e) {
this.props.dispatch({
type: 'SET_MAX_SIZE',
action: {maxSize: e.target.value}
})
type: "SET_MAX_SIZE",
action: { maxSize: e.target.value }
});
}
onMinSizeChange (e) {
onMinSizeChange(e) {
this.props.dispatch({
type: 'SET_MIN_SIZE',
action: {minSize: e.target.value}
})
type: "SET_MIN_SIZE",
action: { minSize: e.target.value }
});
}
onRoomsClick (rooms) {
onRoomsClick(rooms) {
this.props.dispatch({
type: 'UPDATE_ROUTE',
type: "UPDATE_ROUTE",
action: {
params: {rooms}
params: { rooms }
}
})
});
this.props.dispatch({type: 'SET_ROOMS', action: {rooms}})
this.props.dispatch({ type: "SET_ROOMS", action: { rooms } });
}
onCategoryClick (category) {
onCategoryClick(category) {
this.props.dispatch({
type: 'UPDATE_ROUTE',
type: "UPDATE_ROUTE",
action: {
params: {category}
params: { category }
}
})
});
this.props.dispatch({type: 'SET_CATEGORY', action: {category}})
this.props.dispatch({ type: "SET_CATEGORY", action: { category } });
}
onRefreshClick (closeFilters) {
this.updateSearch()
onRefreshClick(closeFilters) {
this.updateSearch();
if (closeFilters) {
this.props.dispatch({
type: 'CLOSE_FILTERS'
})
type: "CLOSE_FILTERS"
});
}
}
onKeyPress (e) {
if (e.key === 'Enter') {
this.updateSearch()
onKeyPress(e) {
if (e.key === "Enter") {
this.updateSearch();
}
}
updateSearch () {
const {minPrice, maxPrice, minSize, maxSize} = this.props.filters
updateSearch() {
const { minPrice, maxPrice, minSize, maxSize } = this.props.filters;
this.props.dispatch({
type: 'UPDATE_ROUTE',
type: "UPDATE_ROUTE",
action: {
params: {
minPrice,
@@ -97,20 +97,20 @@ export default class Filters extends React.Component {
maxSize
}
}
})
this.props.dispatch({type: 'UPDATE_SEARCH'})
});
this.props.dispatch({ type: "UPDATE_SEARCH" });
}
onResetSearch (e) {
onResetSearch(e) {
this.props.dispatch({
type: 'RESET_FILTERS'
})
type: "RESET_FILTERS"
});
}
render () {
const {filters} = this.props
const selectedRooms = val => filters.rooms[val] ? 'selected' : ''
const selectedCategory = val => filters.category[val] ? 'selected' : ''
render() {
const { filters } = this.props;
const selectedRooms = val => filters.rooms[val] ? "selected" : "";
const selectedCategory = val => filters.category[val] ? "selected" : "";
return (
<div className="filters">
@@ -135,7 +135,7 @@ export default class Filters extends React.Component {
onChange={this.onMinPriceChange.bind(this)}
value={formatFilterNumber(filters.minPrice)}
/>
{' '}
{" "}
DO
<input
@@ -206,7 +206,7 @@ export default class Filters extends React.Component {
/>
DO
{' '}
{" "}
<input
onKeyPress={this.onKeyPress.bind(this)}
value={formatFilterNumber(filters.maxSize)}
@@ -247,8 +247,8 @@ export default class Filters extends React.Component {
3
</div>
<div
onClick={this.onRoomsClick.bind(this, '4+')}
className={`filter-btn property-rooms-btn ${selectedRooms('4+')}`}
onClick={this.onRoomsClick.bind(this, "4+")}
className={`filter-btn property-rooms-btn ${selectedRooms("4+")}`}
>
4+
</div>
@@ -262,12 +262,18 @@ export default class Filters extends React.Component {
</div>
<div className="clear-both" />
<div className="filter-bottom">
<div onClick={this.onResetSearch.bind(this)} className="filter-btn">Poništi</div>
<div onClick={this.onRefreshClick.bind(this, true)}
className="filter-btn confirm">Potvrdi</div>
<div onClick={this.onResetSearch.bind(this)} className="filter-btn">
Poništi
</div>
<div
onClick={this.onRefreshClick.bind(this, true)}
className="filter-btn confirm"
>
Potvrdi
</div>
</div>
</div>
)
);
}
}

View File

@@ -630,7 +630,7 @@ class Main extends React.Component {
</div>
<div id="left" style={leftStyle} className={leftClass}>
{this.state.mobileView === 'LIST' && !this.state.listingDetails &&
{this.state.mobileView === 'LIST' && !this.state.listingDetails &&
<div className={ this.state.filtersOpen ? "map-list-view hide": "map-list-view" }>
<Listings
sort={this.state.sort}

View File

@@ -0,0 +1,81 @@
import React from 'react'
import { pacSelectFirst } from '../helpers/googleMaps'
export default class Welcome extends React.Component {
constructor (props) {
super(props)
this.state = {
type: 'SALE'
}
}
componentDidMount () {
const options = {
componentRestrictions: { country: 'BA' },
types: ['geocode']
}
const input = document.getElementById('gmaps-places-input-welcome')
const searchBox = new google.maps.places.Autocomplete(input, options)
pacSelectFirst(input)
input.addEventListener('focus', e => {
e.target.value = ''
})
searchBox.addListener('place_changed', () => {
const place = searchBox.getPlace()
if (place.geometry.viewport) {
const bounds = place.geometry.viewport.toUrlValue()
this.props.onSearch({
bounds,
type: this.state.type
})
} else {
const location = place.geometry.location
this.props.onSearch({
location,
type: this.state.type
})
}
})
}
onSaleClick () {
this.setState({
type: 'SALE'
})
}
onRentClick () {
this.setState({
type: 'RENT'
})
}
render () {
return (
<div>
<div className='welcome-container-bg'>
</div>
<div className='welcome-container'>
<div className='welcome-content'>
<h1>KIVI</h1>
<h2>Pronađi svoj novi dom!</h2>
<button
onClick={this.onSaleClick.bind(this)}>Kupovina</button>
<button onClick={this.onRentClick.bind(this)}>Iznajmljivanje</button>
<input
type='text'
placeholder='Unesite adresu, naselje ili grad'
className='where-to'
id='gmaps-places-input-welcome'
/>
</div>
</div>
</div>
)
}
}