welcome popeup + mobile friendly
BIN
web/dist/static/images/rent_0.png
vendored
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
web/dist/static/images/rent_0_mobile.png
vendored
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
web/dist/static/images/rent_1.png
vendored
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
web/dist/static/images/rent_1_mobile.png
vendored
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
web/dist/static/images/sale_0.png
vendored
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
web/dist/static/images/sale_0_mobile.png
vendored
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
web/dist/static/images/sale_1.png
vendored
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
web/dist/static/images/sale_1_mobile.png
vendored
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
132
web/dist/welcome.css
vendored
@@ -5,25 +5,25 @@
|
|||||||
/*}*/
|
/*}*/
|
||||||
|
|
||||||
.welcome-container h1 {
|
.welcome-container h1 {
|
||||||
font-size: 2em;
|
font-size: 1.2em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-container h2 {
|
.welcome-container h2 {
|
||||||
|
|
||||||
padding-bottom: 25px;
|
/*padding-bottom: 25px;*/
|
||||||
color: #2d3138;
|
color: #2d3138;
|
||||||
font-size: 26px;
|
font-size: 1em;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
letter-spacing: .59px;
|
letter-spacing: .59px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.welcome-container-bg {
|
.welcome-container-bg {
|
||||||
/*background-color: rgb(92, 192, 99);*/
|
/*background-color: rgb(92, 192, 99);*/
|
||||||
background-image: url('static/map.jpg');
|
/*background-image: url('static/map.jpg');*/
|
||||||
/*background-image: url('static/images/sa-bg.jpg');*/
|
background-image: url('static/images/sa-bg.jpg');
|
||||||
|
background-size: auto 100%;
|
||||||
/*background-position: center;*/
|
/*background-position: center;*/
|
||||||
-moz-filter: blur(5px);
|
-moz-filter: blur(5px);
|
||||||
-o-filter: blur(5px);
|
-o-filter: blur(5px);
|
||||||
@@ -40,26 +40,116 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.welcome-container {
|
.welcome-container {
|
||||||
position: fixed;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
top:0;
|
||||||
|
bottom:0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
margin-left: 20px;
|
/*margin-left: 20px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;*/
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 100px;
|
/*padding: 100px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-content {
|
.welcome-content {
|
||||||
/*height: 100%;*/
|
/*height: 100%;*/
|
||||||
margin: 0 auto;
|
/*margin: 0 auto;*/
|
||||||
width: 600px;
|
width: 240px;
|
||||||
background-color: hsla(0,0%,100%,.95);
|
background-color: hsla(0,0%,100%,.95);
|
||||||
box-shadow: 0 2px 4px 0 rgba(73,73,73,.1);
|
box-shadow: 0 2px 4px 0 rgba(73,73,73,.1);
|
||||||
padding: 50px;
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top:40%;
|
||||||
|
/*padding: 50px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome-content .gmaps-places-input-welcome {
|
.buy-button {
|
||||||
|
height: 80px;
|
||||||
width: 100%;
|
width: 80px;
|
||||||
|
background:url('static/images/sale_1_mobile.png') no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
border: none;
|
||||||
|
margin-left: 10%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rent-button{
|
||||||
|
height: 80px;
|
||||||
|
width: 80px;
|
||||||
|
background:url('static/images/rent_0_mobile.png') no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
border: none;
|
||||||
|
margin-left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button{
|
||||||
|
background-color: #b6d53b;
|
||||||
|
margin: 10px;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1em;
|
||||||
|
width: 90%;
|
||||||
|
margin-left:5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 550px) {
|
||||||
|
|
||||||
|
.welcome-container h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-container h2 {
|
||||||
|
|
||||||
|
/*padding-bottom: 25px;*/
|
||||||
|
color: #2d3138;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: 200;
|
||||||
|
text-align: center;
|
||||||
|
letter-spacing: .59px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-content {
|
||||||
|
/*height: 100%;*/
|
||||||
|
/*margin: 0 auto;*/
|
||||||
|
width: 500px;
|
||||||
|
background-color: hsla(0,0%,100%,.95);
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(73,73,73,.1);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top:10%;
|
||||||
|
/*padding: 50px;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-button {
|
||||||
|
height: 150px;
|
||||||
|
width: 150px;
|
||||||
|
background:url('static/images/sale_1_mobile.png') no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
border: none;
|
||||||
|
margin-left: 15%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rent-button{
|
||||||
|
height: 150px;
|
||||||
|
width: 150px;
|
||||||
|
background:url('static/images/rent_0_mobile.png') no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
border: none;
|
||||||
|
margin-left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-button{
|
||||||
|
background-color: #b6d53b;
|
||||||
|
margin: 10px;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4em;
|
||||||
|
width: 90%;
|
||||||
|
margin-left:5%;
|
||||||
|
margin-right: 5%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ class Main extends React.Component {
|
|||||||
filters: {
|
filters: {
|
||||||
rooms: {},
|
rooms: {},
|
||||||
category: {},
|
category: {},
|
||||||
status : {}
|
status : {},
|
||||||
|
adType: 0
|
||||||
},
|
},
|
||||||
mobileView: 'MAP',
|
mobileView: 'MAP',
|
||||||
contact: {
|
contact: {
|
||||||
@@ -34,6 +35,8 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Props : ");
|
||||||
|
console.log(props.initialState);
|
||||||
if (props.initialState) {
|
if (props.initialState) {
|
||||||
props.initialState.sort = props.initialState.sort || state.sort
|
props.initialState.sort = props.initialState.sort || state.sort
|
||||||
state.filters.rooms = props.initialState.rooms
|
state.filters.rooms = props.initialState.rooms
|
||||||
@@ -49,6 +52,7 @@ class Main extends React.Component {
|
|||||||
state.filters.maxSize = props.initialState.maxSize
|
state.filters.maxSize = props.initialState.maxSize
|
||||||
state.filters.minPrice = props.initialState.minPrice
|
state.filters.minPrice = props.initialState.minPrice
|
||||||
state.filters.maxPrice = props.initialState.maxPrice
|
state.filters.maxPrice = props.initialState.maxPrice
|
||||||
|
state.filters.adType = props.initialState.adType
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = state
|
this.state = state
|
||||||
@@ -234,7 +238,8 @@ class Main extends React.Component {
|
|||||||
maxSize,
|
maxSize,
|
||||||
minPrice,
|
minPrice,
|
||||||
maxPrice,
|
maxPrice,
|
||||||
category
|
category,
|
||||||
|
adType
|
||||||
} = this.state.filters
|
} = this.state.filters
|
||||||
|
|
||||||
const bounds = map.getBounds()
|
const bounds = map.getBounds()
|
||||||
@@ -246,6 +251,7 @@ class Main extends React.Component {
|
|||||||
minPrice,
|
minPrice,
|
||||||
maxPrice,
|
maxPrice,
|
||||||
category,
|
category,
|
||||||
|
adType,
|
||||||
page: this.state.page,
|
page: this.state.page,
|
||||||
pins: true
|
pins: true
|
||||||
})
|
})
|
||||||
@@ -404,7 +410,8 @@ class Main extends React.Component {
|
|||||||
maxSize,
|
maxSize,
|
||||||
minPrice,
|
minPrice,
|
||||||
maxPrice,
|
maxPrice,
|
||||||
category
|
category,
|
||||||
|
adType
|
||||||
} = this.state.filters
|
} = this.state.filters
|
||||||
|
|
||||||
const bounds = map.getBounds()
|
const bounds = map.getBounds()
|
||||||
@@ -416,6 +423,7 @@ class Main extends React.Component {
|
|||||||
minPrice,
|
minPrice,
|
||||||
maxPrice,
|
maxPrice,
|
||||||
category,
|
category,
|
||||||
|
adType,
|
||||||
page: this.state.page,
|
page: this.state.page,
|
||||||
sort: this.state.sort
|
sort: this.state.sort
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,59 +1,43 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { pacSelectFirst } from '../helpers/googleMaps'
|
import {AD_TYPE_SALE, AD_TYPE_RENT} from '../../../common/enums';
|
||||||
|
|
||||||
export default class Welcome extends React.Component {
|
export default class Welcome extends React.Component {
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
type: 'SALE'
|
type: AD_TYPE_SALE,
|
||||||
|
buyButtonImg: 'static/images/sale_1_mobile.png',
|
||||||
|
rentButtonImg: 'static/images/rent_0_mobile.png'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 () {
|
onSaleClick () {
|
||||||
this.setState({
|
this.setState({
|
||||||
type: 'SALE'
|
type: AD_TYPE_SALE,
|
||||||
|
buyButtonImg: 'static/images/sale_1_mobile.png',
|
||||||
|
rentButtonImg: 'static/images/rent_0_mobile.png'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onRentClick () {
|
onRentClick () {
|
||||||
this.setState({
|
this.setState({
|
||||||
type: 'RENT'
|
type: AD_TYPE_RENT,
|
||||||
|
buyButtonImg: 'static/images/sale_0_mobile.png',
|
||||||
|
rentButtonImg: 'static/images/rent_1_mobile.png'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSearchClick () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
let style1 = {
|
||||||
|
background:'url(' + this.state.buyButtonImg + ')',
|
||||||
|
backgrounSize: 'cover'
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='welcome-container-bg'>
|
<div className='welcome-container-bg'>
|
||||||
@@ -63,15 +47,11 @@ export default class Welcome extends React.Component {
|
|||||||
<div className='welcome-content'>
|
<div className='welcome-content'>
|
||||||
<h1>KIVI</h1>
|
<h1>KIVI</h1>
|
||||||
<h2>Pronađi svoj novi dom!</h2>
|
<h2>Pronađi svoj novi dom!</h2>
|
||||||
<button
|
<div>
|
||||||
onClick={this.onSaleClick.bind(this)}>Kupovina</button>
|
<button className='buy-button' style={{background:"url("+this.state.buyButtonImg+") no-repeat"}} onClick={this.onSaleClick.bind(this)}></button>
|
||||||
<button onClick={this.onRentClick.bind(this)}>Iznajmljivanje</button>
|
<button className='rent-button' style={{background:"url("+this.state.rentButtonImg+") no-repeat"}} onClick={this.onRentClick.bind(this)}></button>
|
||||||
<input
|
</div>
|
||||||
type='text'
|
<button className='search-button' onClick={()=>this.props.onSearch({adType: this.state.type})} >TRAŽI</button>
|
||||||
placeholder='Unesite adresu, naselje ili grad'
|
|
||||||
className='where-to'
|
|
||||||
id='gmaps-places-input-welcome'
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,84 +1,84 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import {render} from 'react-dom'
|
import {render} from 'react-dom';
|
||||||
import Main from './components/Main'
|
import Main from './components/Main';
|
||||||
import Welcome from './components/Welcome'
|
import Welcome from './components/Welcome';
|
||||||
|
|
||||||
const getInitialState = url => {
|
const getInitialState = url => {
|
||||||
const params = window.location.search.substr(1).split('&')
|
const params = window.location.search.substr (1).split ('&');
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
rooms: {},
|
rooms: {},
|
||||||
category: {}
|
category: {},
|
||||||
}
|
};
|
||||||
|
|
||||||
for (const param of params) {
|
for (const param of params) {
|
||||||
const [key, value] = param.split('=')
|
const [key, value] = param.split ('=');
|
||||||
if (key === 'rooms' && value !== '') {
|
if (key === 'rooms' && value !== '') {
|
||||||
initialState.rooms = {}
|
initialState.rooms = {};
|
||||||
value.split(',').forEach(k => {
|
value.split (',').forEach (k => {
|
||||||
initialState.rooms[parseInt(k)] = true
|
initialState.rooms[parseInt (k)] = true;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'category' && value !== '') {
|
if (key === 'category' && value !== '') {
|
||||||
initialState.category = {}
|
initialState.category = {};
|
||||||
value.split(',').forEach(k => {
|
value.split (',').forEach (k => {
|
||||||
initialState.category[parseInt(k)] = true
|
initialState.category[parseInt (k)] = true;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'sort') {
|
if (key === 'sort') {
|
||||||
initialState.sort = value
|
initialState.sort = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'bounds') {
|
if (key === 'bounds') {
|
||||||
initialState.bounds = value
|
initialState.bounds = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'listingId') {
|
if (key === 'listingId') {
|
||||||
initialState.listingId = value
|
initialState.listingId = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'type') {
|
if (key === 'adType') {
|
||||||
initialState.type = value
|
initialState.adType = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === 'zoom') {
|
if (key === 'zoom') {
|
||||||
initialState.zoom = parseInt(value)
|
initialState.zoom = parseInt (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['minSize', 'maxSize', 'minPrice', 'maxPrice'].includes(key)) {
|
if (['minSize', 'maxSize', 'minPrice', 'maxPrice'].includes (key)) {
|
||||||
initialState[key] = parseFloat(value)
|
initialState[key] = parseFloat (value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return initialState
|
return initialState;
|
||||||
}
|
};
|
||||||
|
|
||||||
const root = document.getElementById('root')
|
const root = document.getElementById ('root');
|
||||||
const initialState = getInitialState(window.location)
|
const initialState = getInitialState (window.location);
|
||||||
|
|
||||||
const renderMain = (additionalState = {}) => {
|
const renderMain = (additionalState = {}) => {
|
||||||
const main = <Main initialState={{...initialState, ...additionalState}} />
|
const main = <Main initialState={{...initialState, ...additionalState}} />;
|
||||||
render(main, root)
|
render (main, root);
|
||||||
}
|
};
|
||||||
|
|
||||||
renderMain()
|
//renderMain ();
|
||||||
|
|
||||||
// disable temp
|
// disable temp
|
||||||
/*
|
|
||||||
if (Object.keys(initialState).length === 2 &&
|
if (
|
||||||
window.localStorage.getItem('lastLoad') == null) {
|
Object.keys (initialState).length === 2 &&
|
||||||
const onSearch = ({bounds, type, location}) => {
|
window.localStorage.getItem ('lastLoad') == null
|
||||||
window.location = `/?bounds=${bounds}&type=${type}`
|
) {
|
||||||
//renderMain({
|
const onSearch = ({adType}) => {
|
||||||
//bounds,
|
|
||||||
//type
|
console.log("onSearch()");
|
||||||
//})
|
//window.location = `/?adType=${adType}`;
|
||||||
}
|
renderMain({adType})
|
||||||
const welcome = <Welcome onSearch={onSearch} />
|
};
|
||||||
render(welcome, root)
|
const welcome = <Welcome onSearch={onSearch} />;
|
||||||
|
render (welcome, root);
|
||||||
} else {
|
} else {
|
||||||
renderMain()
|
renderMain ();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export const loadProperties = (
|
|||||||
maxSize = '',
|
maxSize = '',
|
||||||
rooms = {},
|
rooms = {},
|
||||||
category = {},
|
category = {},
|
||||||
|
adType=1,
|
||||||
page = 1,
|
page = 1,
|
||||||
pins = false,
|
pins = false,
|
||||||
sort = ''
|
sort = ''
|
||||||
@@ -50,7 +51,7 @@ export const loadProperties = (
|
|||||||
|
|
||||||
// TODO: handle errors
|
// TODO: handle errors
|
||||||
//return fetch(process.env.API_URL + '/api/search', {
|
//return fetch(process.env.API_URL + '/api/search', {
|
||||||
let url = `http://${BASE_URL}:3001/api/search/listings?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}&minSize=${minSize}&maxSize=${maxSize}&category=${allCategories}&page=${page}&pins=${pins}&sort=${sort}`
|
let url = `http://${BASE_URL}:3001/api/search/listings?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}&minSize=${minSize}&maxSize=${maxSize}&adType=${adType}&category=${allCategories}&page=${page}&pins=${pins}&sort=${sort}`
|
||||||
|
|
||||||
return fetch(
|
return fetch(
|
||||||
url,
|
url,
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ module.exports = {
|
|||||||
filename: "app.bundle.js",
|
filename: "app.bundle.js",
|
||||||
publicPath: "http://0.0.0.0:8080/"
|
publicPath: "http://0.0.0.0:8080/"
|
||||||
},
|
},
|
||||||
|
devServer: {
|
||||||
|
// .. rest of devserver options
|
||||||
|
|
||||||
|
host: '0.0.0.0',
|
||||||
|
disableHostCheck: true
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
|
|||||||