Compare commits
62 Commits
wizard
...
google-map
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fbacb326f | ||
|
|
be416ffc0c | ||
|
|
a3d9a82fee | ||
|
|
6772f8a953 | ||
|
|
89a3c9e355 | ||
|
|
dd38602c5a | ||
|
|
a3f76d20fe | ||
|
|
fc1275566e | ||
|
|
c64ee42914 | ||
|
|
aa3c965d5c | ||
|
|
126da48852 | ||
|
|
58ae430564 | ||
|
|
315a29749c | ||
|
|
02bee9cf2c | ||
|
|
1c2847509a | ||
|
|
87dc742e41 | ||
|
|
70ddc1f734 | ||
|
|
2c415bbd79 | ||
|
|
b07eb5bbeb | ||
|
|
53585d3ae1 | ||
|
|
c652a306db | ||
|
|
b15295bfe6 | ||
|
|
7ad1117cae | ||
|
|
393f6731e6 | ||
|
|
93faa7c9e3 | ||
|
|
93f5d8071e | ||
|
|
7192c28c07 | ||
|
|
76f9457d4f | ||
|
|
68172951ed | ||
|
|
dbf40b199e | ||
|
|
4309bc709d | ||
|
|
4323017d02 | ||
|
|
42505a7089 | ||
|
|
1542310a81 | ||
|
|
c505062770 | ||
|
|
ab681e5eeb | ||
|
|
616eddbb19 | ||
|
|
e5eb6b99a2 | ||
|
|
27fa721627 | ||
|
|
9fdfce49ed | ||
|
|
59723410b6 | ||
|
|
51ed3551c7 | ||
|
|
58177a8cce | ||
|
|
864b917b4f | ||
|
|
a2f6f033bf | ||
|
|
64f2cb82a8 | ||
|
|
17492eb52c | ||
|
|
298c901759 | ||
|
|
c534c1ee34 | ||
|
|
2380c85122 | ||
|
|
0f7e9f9285 | ||
|
|
dee4df9bd8 | ||
|
|
4248e6304a | ||
|
|
9fd9fe8b82 | ||
|
|
467d551857 | ||
|
|
28f95b9c05 | ||
|
|
9aba66c273 | ||
|
|
d03e85a0dc | ||
|
|
9d49e72bb4 | ||
|
|
efe2dd66a3 | ||
|
|
5f2fee504a | ||
|
|
add905c793 |
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
FROM postgres:11.3
|
||||||
|
|
||||||
|
ENV POSTGIS_MAJOR 2.4
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get --assume-yes install software-properties-common postgis\
|
||||||
|
&& rm -rf /var/lib/apt/lists/
|
||||||
|
|
||||||
|
RUN mkdir -p /docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
CMD ["postgres"]
|
||||||
36
README.md
36
README.md
@@ -1,12 +1,36 @@
|
|||||||
# web
|
# MarketAlert
|
||||||
|
|
||||||
|
|
||||||
The purpose of this project is to build a web application that enables subscribing to notifications when new products are published on various ad based marketplaces. The MVP will be only based on OLX.ba
|
The purpose of this project is to build a web application that enables subscribing to notifications when new products are published on various ad based marketplaces. The MVP will be only based on OLX.ba
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
ENV:
|
### Setup with npm commands
|
||||||
JAWSDB_URL='mysql://sq4dlf9mz49avli0:gqy5vzmzyhp0837x@tuy8t6uuvh43khkk.cbetxkdyhwsb.us-east-1.rds.amazonaws.com:3306/rxhzg1550441ftqk'
|
|
||||||
|
|
||||||
Run with:
|
1. Install packages
|
||||||
$ npm start
|
`npm install`
|
||||||
|
|
||||||
|
2. Run setup script
|
||||||
|
`npm run setup`
|
||||||
|
this will create and run postgres image and then execute migrations
|
||||||
|
|
||||||
|
3. Run app
|
||||||
|
`npm start` to run app without restart on changes or
|
||||||
|
`npm run start-mon` to run app with automatic restart on code change
|
||||||
|
|
||||||
|
|
||||||
|
### Manual setup
|
||||||
|
|
||||||
|
1. Create postgres docker image
|
||||||
|
`docker build -t marketalerts .`
|
||||||
|
|
||||||
|
2. Run postgres image with
|
||||||
|
`docker run --name pg_marketalerts -d -p 5432:5432 marketalerts`
|
||||||
|
|
||||||
|
3. Install packages
|
||||||
|
`npm install`
|
||||||
|
|
||||||
|
4. Run migrations from `app` folder
|
||||||
|
`npm run migrate` or `npx sequelize db:migrate`
|
||||||
|
|
||||||
|
5. Run app
|
||||||
|
`npm start` or `npm run start-mon` to run app with automatic restart on code change
|
||||||
|
|||||||
15
app/config/config.json
Normal file
15
app/config/config.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"development": {
|
||||||
|
"username": "docker",
|
||||||
|
"password": "docker",
|
||||||
|
"database": "marketalerts",
|
||||||
|
"port": "5432",
|
||||||
|
"dialect": "postgres"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"use_env_variable": "DATABASE_URL"
|
||||||
|
},
|
||||||
|
"production": {
|
||||||
|
"use_env_variable": "DATABASE_URL"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const getDobrodosli = (req,res) => {
|
|
||||||
res.render('dobrodosli', { nextStep: '/vrstanekretnine' } );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getDobrodosli
|
|
||||||
};
|
|
||||||
26
app/controllers/gardenSizes.js
Normal file
26
app/controllers/gardenSizes.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { gardenSizes, getRealEstateTypeEnum } = require('../helpers/enums');
|
||||||
|
|
||||||
|
const getGardenSize = (req,res) => {
|
||||||
|
res.render('gardenSize', { gardenSizes });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postGardenSize = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
|
||||||
|
const nextStepPage = req.query.nextStep || 'cijena';
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
|
||||||
|
|
||||||
|
const realEstateType = getRealEstateTypeEnum(request.realEstateType);
|
||||||
|
if (realEstateType && realEstateType.hasGardenSize) {
|
||||||
|
request.gardenSize = req.body.gardensize;
|
||||||
|
await request.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getGardenSize,
|
||||||
|
postGardenSize
|
||||||
|
};
|
||||||
7
app/controllers/goAgain.js
Normal file
7
app/controllers/goAgain.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const getGoAgain = async (req,res) => {
|
||||||
|
res.render('goAgain');
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getGoAgain
|
||||||
|
};
|
||||||
25
app/controllers/municipalities.js
Normal file
25
app/controllers/municipalities.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { getMunicipalitiesForRegion, getMunicipalityName } = require('../helpers/codes');
|
||||||
|
|
||||||
|
const getMunicipality = async (req, res) => {
|
||||||
|
let request = await currentRERequest(req);
|
||||||
|
const municipalities = getMunicipalitiesForRegion(request.region);
|
||||||
|
|
||||||
|
res.render('municipality', { municipalities });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postMunicipality = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
const nextStepPage = req.query.nextStep || 'naselje';
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}/${getMunicipalityName(request.region, req.body.municipality)}`;
|
||||||
|
|
||||||
|
request.municipality = req.body.municipality;
|
||||||
|
await request.save();
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getMunicipality,
|
||||||
|
postMunicipality
|
||||||
|
};
|
||||||
35
app/controllers/neighborhoodMap.js
Normal file
35
app/controllers/neighborhoodMap.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
|
||||||
|
const getNeighborhood = async (req, res) => {
|
||||||
|
const municipality = req.params.municipality
|
||||||
|
const nextStep = req.query.nextStep || '/';
|
||||||
|
|
||||||
|
res.render('neighborhoodMap', {
|
||||||
|
nextStep,
|
||||||
|
municipality
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const postNeighborhood = async (req, res) => {
|
||||||
|
let request = await currentRERequest(req);
|
||||||
|
const northWest = [req.body.west, req.body.north];
|
||||||
|
const northEast = [req.body.east, req.body.north];
|
||||||
|
const southEast = [req.body.east, req.body.south];
|
||||||
|
const southWest = [req.body.west, req.body.south];
|
||||||
|
|
||||||
|
request.bounding_box = {
|
||||||
|
type: 'Polygon', coordinates: [
|
||||||
|
[northWest, northEast, southEast,
|
||||||
|
southWest, northWest]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
await request.save();
|
||||||
|
const nextStep = req.query.nextStep || `/povrsina/${request.uniqueId}`;
|
||||||
|
res.redirect(nextStep);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getNeighborhood,
|
||||||
|
postNeighborhood
|
||||||
|
};
|
||||||
23
app/controllers/prices.js
Normal file
23
app/controllers/prices.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { prices } = require('../helpers/enums');
|
||||||
|
|
||||||
|
const getPrice = (req,res) => {
|
||||||
|
res.render('price', { prices });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postPrice = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
|
||||||
|
const nextStepPage = req.query.nextStep || 'pregled';
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
|
||||||
|
|
||||||
|
request.price = req.body.price;
|
||||||
|
await request.save();
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getPrice,
|
||||||
|
postPrice
|
||||||
|
};
|
||||||
76
app/controllers/queryReview.js
Normal file
76
app/controllers/queryReview.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { getRegionName, getMunicipalityName } = require('../helpers/codes');
|
||||||
|
const { realEstateTypes, sizes, gardenSizes, prices, getEnumTypeTitle, getRealEstateTypeEnum } = require('../helpers/enums');
|
||||||
|
|
||||||
|
const getQueryReview = async (req,res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
const nextStep = req.query.nextStep;
|
||||||
|
|
||||||
|
if (!request || !request.dataValues) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { realEstateType, region, municipality, size, gardenSize, price } = request.dataValues;
|
||||||
|
|
||||||
|
const realEstateTypeObject = getRealEstateTypeEnum(realEstateType);
|
||||||
|
const enableGardenSizeEdit = realEstateTypeObject ? realEstateTypeObject.hasGardenSize : false;
|
||||||
|
|
||||||
|
const realEstateTypeTitle = realEstateType ? getEnumTypeTitle(realEstateTypes, realEstateType) : null;
|
||||||
|
const regionName = region ? getRegionName(region) : null;
|
||||||
|
const municipalityName = (region && municipality) ? getMunicipalityName(region, municipality) : null;
|
||||||
|
const sizeTitle = size ? getEnumTypeTitle(sizes, size) : null;
|
||||||
|
const gardenSizeTitle = gardenSize ? getEnumTypeTitle(gardenSizes, gardenSize) : null;
|
||||||
|
const priceTitle = price ? getEnumTypeTitle(prices, price) : null;
|
||||||
|
|
||||||
|
const uniqueId = request.dataValues.uniqueId ? request.dataValues.uniqueId : '';
|
||||||
|
|
||||||
|
const queryData = [
|
||||||
|
{
|
||||||
|
id: 'realEstateType',
|
||||||
|
title: realEstateTypeTitle,
|
||||||
|
url: `/vrstanekretnine/${uniqueId}?nextStep=pregled`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'region',
|
||||||
|
title: regionName,
|
||||||
|
url: `/grad/${uniqueId}?nextStep=mjesto`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'municipality',
|
||||||
|
title: municipalityName,
|
||||||
|
url: `/mjesto/${uniqueId}?nextStep=pregled`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'size',
|
||||||
|
title: sizeTitle,
|
||||||
|
url: `/povrsina/${uniqueId}?nextStep=pregled`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'gardenSize',
|
||||||
|
title: gardenSizeTitle,
|
||||||
|
url: enableGardenSizeEdit ? `/okucnica/${uniqueId}?nextStep=pregled` : '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'price',
|
||||||
|
title: priceTitle,
|
||||||
|
url: `/cijena/${uniqueId}?nextStep=pregled`
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
res.render('queryReview', {
|
||||||
|
nextStep,
|
||||||
|
queryData,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const postQueryReview = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
const nextStep = req.query.nextStep || `/posalji/${request.uniqueId}`;
|
||||||
|
|
||||||
|
res.redirect(nextStep);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getQueryReview,
|
||||||
|
postQueryReview
|
||||||
|
};
|
||||||
32
app/controllers/querySubmit.js
Normal file
32
app/controllers/querySubmit.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { isValidEmail } = require('../helpers/email');
|
||||||
|
|
||||||
|
const getQuerySubmit = async (req,res) => {
|
||||||
|
const nextStep = req.query.nextStep;
|
||||||
|
const error = req.query.error;
|
||||||
|
|
||||||
|
res.render('querySubmit', {
|
||||||
|
nextStep,
|
||||||
|
error
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const postQuerySubmit = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
const nextStep = req.query.nextStep || '/ponovo';
|
||||||
|
|
||||||
|
const emailInput = req.body.email;
|
||||||
|
|
||||||
|
if (isValidEmail(emailInput)){
|
||||||
|
request.email = req.body.email;
|
||||||
|
await request.save();
|
||||||
|
res.redirect(nextStep);
|
||||||
|
} else {
|
||||||
|
res.redirect('?error=1');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getQuerySubmit,
|
||||||
|
postQuerySubmit
|
||||||
|
};
|
||||||
44
app/controllers/realEstateTypes.js
Normal file
44
app/controllers/realEstateTypes.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
const db = require('../models/index');
|
||||||
|
|
||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { realEstateTypes, getRealEstateTypeEnum } = require('../helpers/enums');
|
||||||
|
|
||||||
|
|
||||||
|
const getRealEstateTypes = (req,res) => {
|
||||||
|
res.render('realEstateType', { realEstateTypes });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postRealEstateTypes = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
|
||||||
|
const nextStepPage = req.query.nextStep || 'grad';
|
||||||
|
|
||||||
|
if (request && request.uniqueId) {
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
|
||||||
|
request.realEstateType = req.body.realestatetype;
|
||||||
|
if (!getRealEstateTypeEnum(request.realEstateType).hasGardenSize){
|
||||||
|
request.gardenSize = null;
|
||||||
|
}
|
||||||
|
await request.save();
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl)
|
||||||
|
} else {
|
||||||
|
db.RealEstateRequest.create({
|
||||||
|
realEstateType: req.body.realestatetype
|
||||||
|
}).then( (result) => {
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${result.uniqueId}`;
|
||||||
|
res.redirect(nextStepUrl);
|
||||||
|
}).catch( (e) => {
|
||||||
|
res.send(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getRealEstateTypes,
|
||||||
|
postRealEstateTypes
|
||||||
|
};
|
||||||
27
app/controllers/regions.js
Normal file
27
app/controllers/regions.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { getRegions } = require('../helpers/codes');
|
||||||
|
|
||||||
|
const regions = getRegions();
|
||||||
|
|
||||||
|
const getRegion = (req,res) => {
|
||||||
|
res.render('region', { regions });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postRegion = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
|
||||||
|
const nextStepQueryParam = req.query.nextStep ? '?nextStep=pregled' : '';
|
||||||
|
const nextStepPage = req.query.nextStep || 'mjesto';
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}${nextStepQueryParam}`;
|
||||||
|
|
||||||
|
request.region = req.body.region;
|
||||||
|
request.municipality = null;
|
||||||
|
await request.save();
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl)
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getRegion,
|
||||||
|
postRegion
|
||||||
|
};
|
||||||
26
app/controllers/sizes.js
Normal file
26
app/controllers/sizes.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
const { currentRERequest } = require('../helpers/url');
|
||||||
|
const { sizes, getRealEstateTypeEnum } = require('../helpers/enums');
|
||||||
|
|
||||||
|
const getSize = (req,res) => {
|
||||||
|
res.render('size', { sizes });
|
||||||
|
};
|
||||||
|
|
||||||
|
const postSize = async (req, res) => {
|
||||||
|
const request = await currentRERequest(req);
|
||||||
|
|
||||||
|
const realEstateType = getRealEstateTypeEnum(request.realEstateType);
|
||||||
|
|
||||||
|
const nextStep = realEstateType && realEstateType.hasGardenSize ? 'okucnica' : 'cijena';
|
||||||
|
const nextStepPage = req.query.nextStep || nextStep;
|
||||||
|
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
|
||||||
|
|
||||||
|
request.size = req.body.size;
|
||||||
|
await request.save();
|
||||||
|
|
||||||
|
res.redirect(nextStepUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getSize,
|
||||||
|
postSize
|
||||||
|
};
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
const getVrstaNekretnine = (req,res) => {
|
|
||||||
res.render('vrsta_nekretnine', { nextStep: '/' } );
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getVrstaNekretnine
|
|
||||||
};
|
|
||||||
7
app/controllers/welcome.js
Normal file
7
app/controllers/welcome.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const getWelcome = (req,res) => {
|
||||||
|
res.render('welcome', { nextStep: '/vrstanekretnine' } );
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getWelcome
|
||||||
|
};
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
const Sequelize = require("sequelize");
|
|
||||||
const sequelize = new Sequelize(process.env.JAWSDB_URL);
|
|
||||||
|
|
||||||
module.exports = sequelize;
|
|
||||||
912
app/helpers/codes.js
Normal file
912
app/helpers/codes.js
Normal file
@@ -0,0 +1,912 @@
|
|||||||
|
const regions = [
|
||||||
|
{
|
||||||
|
"name":" Sarajevo",
|
||||||
|
"id":"sarajevo",
|
||||||
|
"olxid": "9",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Hadžići",
|
||||||
|
"id":"hadii",
|
||||||
|
"olxid":"3817"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ilidža",
|
||||||
|
"id":"ilida",
|
||||||
|
"olxid":"3879"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ilijaš",
|
||||||
|
"id":"ilija",
|
||||||
|
"olxid":"3892"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sarajevo - Centar",
|
||||||
|
"id":"sarajevocentar",
|
||||||
|
"olxid":"3812"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sarajevo-Novi Grad",
|
||||||
|
"id":"sarajevonovigrad",
|
||||||
|
"olxid":"3969"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sarajevo-Novo Sarajevo",
|
||||||
|
"id":"sarajevonovosarajevo",
|
||||||
|
"olxid":"5896"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sarajevo-Stari Grad",
|
||||||
|
"id":"sarajevostarigrad",
|
||||||
|
"olxid":"4048"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Trnovo",
|
||||||
|
"id":"trnovo",
|
||||||
|
"olxid":"4063"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Vogošća",
|
||||||
|
"id":"vogoa",
|
||||||
|
"olxid":"4126"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Unsko-sanski",
|
||||||
|
"id":"unskosanski",
|
||||||
|
"olxid": "9",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Bihać",
|
||||||
|
"id":"biha",
|
||||||
|
"olxid":"75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Bosanska Krupa",
|
||||||
|
"id":"bosanskakrupa",
|
||||||
|
"olxid":"373"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Bosanski Petrovac",
|
||||||
|
"id":"bosanskipetrovac",
|
||||||
|
"olxid":"504"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Bužim",
|
||||||
|
"id":"buim",
|
||||||
|
"olxid":"374"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Cazin",
|
||||||
|
"id":"cazin",
|
||||||
|
"olxid":"857"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ključ",
|
||||||
|
"id":"klju",
|
||||||
|
"olxid":"2362"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sanski Most",
|
||||||
|
"id":"sanskimost",
|
||||||
|
"olxid":"3738"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Velika Kladuša",
|
||||||
|
"id":"velikakladua",
|
||||||
|
"olxid":"5122"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Posavski",
|
||||||
|
"id":"posavski",
|
||||||
|
"olxid": "15",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Domaljevac",
|
||||||
|
"id":"domaljevac",
|
||||||
|
"olxid":"6144"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Odžak",
|
||||||
|
"id":"odak",
|
||||||
|
"olxid":"424"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Orašje",
|
||||||
|
"id":"oraje",
|
||||||
|
"olxid":"3252"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Šamac",
|
||||||
|
"id":"amac",
|
||||||
|
"olxid":"540"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Tuzlanski",
|
||||||
|
"id":"tuzlanski",
|
||||||
|
"olxid": "15",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Banovići",
|
||||||
|
"id":"banovii",
|
||||||
|
"olxid":"2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Doboj-Istok",
|
||||||
|
"id":"dobojistok",
|
||||||
|
"olxid":"1090"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Gradačac",
|
||||||
|
"id":"gradaac",
|
||||||
|
"olxid":"1854"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Gračanica",
|
||||||
|
"id":"graanica",
|
||||||
|
"olxid":"1826"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kalesija",
|
||||||
|
"id":"kalesija",
|
||||||
|
"olxid":"2129"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kladanj",
|
||||||
|
"id":"kladanj",
|
||||||
|
"olxid":"2319"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Lukavac",
|
||||||
|
"id":"lukavac",
|
||||||
|
"olxid":"2840"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sapna",
|
||||||
|
"id":"sapna",
|
||||||
|
"olxid":"5699"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Srebrenik",
|
||||||
|
"id":"srebrenik",
|
||||||
|
"olxid":"4391"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Teočak",
|
||||||
|
"id":"teoak",
|
||||||
|
"olxid":"5010"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Tuzla",
|
||||||
|
"id":"tuzla",
|
||||||
|
"olxid":"4944"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Čelić",
|
||||||
|
"id":"eli",
|
||||||
|
"olxid":"2801"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Živinice",
|
||||||
|
"id":"ivinice",
|
||||||
|
"olxid":"5774"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Zeničko-dobojski",
|
||||||
|
"id":"zenickodobojski",
|
||||||
|
"olxid": "15",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Breza",
|
||||||
|
"id":"breza",
|
||||||
|
"olxid":"704"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Doboj-Jug",
|
||||||
|
"id":"dobojjug",
|
||||||
|
"olxid":"1122"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kakanj",
|
||||||
|
"id":"kakanj",
|
||||||
|
"olxid":"2022"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Maglaj",
|
||||||
|
"id":"maglaj",
|
||||||
|
"olxid":"2941"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Olovo",
|
||||||
|
"id":"olovo",
|
||||||
|
"olxid":"1925"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Tešanj",
|
||||||
|
"id":"teanj",
|
||||||
|
"olxid":"4594"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Usora",
|
||||||
|
"id":"usora",
|
||||||
|
"olxid":"1087"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Vareš",
|
||||||
|
"id":"vare",
|
||||||
|
"olxid":"5037"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Visoko",
|
||||||
|
"id":"visoko",
|
||||||
|
"olxid":"5171"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Zavidovići",
|
||||||
|
"id":"zavidovii",
|
||||||
|
"olxid":"5548"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Zenica",
|
||||||
|
"id":"zenica",
|
||||||
|
"olxid":"4571"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Žepče",
|
||||||
|
"id":"epe",
|
||||||
|
"olxid":"2940"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Bosansko-podrinjski",
|
||||||
|
"id":"bosanskopodrinjski",
|
||||||
|
"olxid": "15",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Foča",
|
||||||
|
"id":"foa",
|
||||||
|
"olxid":"1289"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Goražde",
|
||||||
|
"id":"gorade",
|
||||||
|
"olxid":"1588"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Pale",
|
||||||
|
"id":"pale",
|
||||||
|
"olxid":"3546"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Srednjobosanski",
|
||||||
|
"id":"srednjobosanski",
|
||||||
|
"olxid": "6",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Bugojno",
|
||||||
|
"id":"bugojno",
|
||||||
|
"olxid":"732"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Busovača",
|
||||||
|
"id":"busovaa",
|
||||||
|
"olxid":"810"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Dobretići",
|
||||||
|
"id":"dobretii",
|
||||||
|
"olxid":"4151"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Donji Vakuf",
|
||||||
|
"id":"donjivakuf",
|
||||||
|
"olxid":"1160"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Fojnica",
|
||||||
|
"id":"fojnica",
|
||||||
|
"olxid":"1407"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Gornji Vakuf - Uskoplje",
|
||||||
|
"id":"gornjivakufuskoplje",
|
||||||
|
"olxid":"1775"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Jajce",
|
||||||
|
"id":"jajce",
|
||||||
|
"olxid":"1960"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kiseljak",
|
||||||
|
"id":"kiseljak",
|
||||||
|
"olxid":"2237"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kreševo",
|
||||||
|
"id":"kreevo",
|
||||||
|
"olxid":"2608"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Novi Travnik",
|
||||||
|
"id":"novitravnik",
|
||||||
|
"olxid":"3477"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Travnik",
|
||||||
|
"id":"travnik",
|
||||||
|
"olxid":"4678"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Vitez",
|
||||||
|
"id":"vitez",
|
||||||
|
"olxid":"5422"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Hercegovačko-neretvanski",
|
||||||
|
"id":"hercegovackoneretvanski",
|
||||||
|
"olxid": "7",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Grad Mostar",
|
||||||
|
"id":"gradmostar",
|
||||||
|
"olxid":"3017"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Jablanica",
|
||||||
|
"id":"jablanica",
|
||||||
|
"olxid":"1930"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Konjic",
|
||||||
|
"id":"konjic",
|
||||||
|
"olxid":"2169"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Neum",
|
||||||
|
"id":"neum",
|
||||||
|
"olxid":"3111"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Prozor",
|
||||||
|
"id":"prozor",
|
||||||
|
"olxid":"3421"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ravno",
|
||||||
|
"id":"ravno",
|
||||||
|
"olxid":"4769"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Stolac",
|
||||||
|
"id":"stolac",
|
||||||
|
"olxid":"4439"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Čapljina",
|
||||||
|
"id":"apljina",
|
||||||
|
"olxid":"947"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Čitluk",
|
||||||
|
"id":"itluk",
|
||||||
|
"olxid":"1009"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Zapadno-hercegovački",
|
||||||
|
"id":"zapadnohercegovacki",
|
||||||
|
"olxid": "8",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Grude",
|
||||||
|
"id":"grude",
|
||||||
|
"olxid":"1892"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ljubuški",
|
||||||
|
"id":"ljubuki",
|
||||||
|
"olxid":"2905"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Posušje",
|
||||||
|
"id":"posuje",
|
||||||
|
"olxid":"3268"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Široki Brijeg",
|
||||||
|
"id":"irokibrijeg",
|
||||||
|
"olxid":"2708"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Livanjski",
|
||||||
|
"id":"livanjski",
|
||||||
|
"olxid": "10",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Bosansko Grahovo",
|
||||||
|
"id":"bosanskograhovo",
|
||||||
|
"olxid":"560"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Drvar",
|
||||||
|
"id":"drvar",
|
||||||
|
"olxid":"4640"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Glamoč",
|
||||||
|
"id":"glamo",
|
||||||
|
"olxid":"1533"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kupres",
|
||||||
|
"id":"kupres",
|
||||||
|
"olxid":"2635"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Livno",
|
||||||
|
"id":"livno",
|
||||||
|
"olxid":"2741"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Tomislavgrad",
|
||||||
|
"id":"tomislavgrad",
|
||||||
|
"olxid":"1228"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Banjalučka",
|
||||||
|
"id":"banjalučka",
|
||||||
|
"olxid": "14",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Banja Luka",
|
||||||
|
"id":"banjaluka",
|
||||||
|
"olxid":"21"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Gradiška",
|
||||||
|
"id":"gradika",
|
||||||
|
"olxid":"305"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Istočni Drvar",
|
||||||
|
"id":"istonidrvar",
|
||||||
|
"olxid":"4662"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Jezero",
|
||||||
|
"id":"jezero",
|
||||||
|
"olxid":"1965"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kneževo",
|
||||||
|
"id":"kneevo",
|
||||||
|
"olxid":"4147"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kostajnica",
|
||||||
|
"id":"kostajnica",
|
||||||
|
"olxid":"6142"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kotor Varoš",
|
||||||
|
"id":"kotorvaro",
|
||||||
|
"olxid":"2574"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kozarska Dubica",
|
||||||
|
"id":"kozarskadubica",
|
||||||
|
"olxid":"244"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Krupa na uni",
|
||||||
|
"id":"krupanauni",
|
||||||
|
"olxid":"382"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kupres ",
|
||||||
|
"id":"kupres",
|
||||||
|
"olxid":"2654"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Laktaši",
|
||||||
|
"id":"laktai",
|
||||||
|
"olxid":"2671"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Mrkonjić Grad",
|
||||||
|
"id":"mrkonjigrad",
|
||||||
|
"olxid":"3073"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Novi Grad",
|
||||||
|
"id":"novigrad",
|
||||||
|
"olxid":"444"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Oštra Luka",
|
||||||
|
"id":"otraluka",
|
||||||
|
"olxid":"3737"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Petrovac",
|
||||||
|
"id":"petrovac",
|
||||||
|
"olxid":"515"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Prijedor",
|
||||||
|
"id":"prijedor",
|
||||||
|
"olxid":"3287"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Prnjavor",
|
||||||
|
"id":"prnjavor",
|
||||||
|
"olxid":"3358"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ribnik",
|
||||||
|
"id":"ribnik",
|
||||||
|
"olxid":"2365"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Srbac",
|
||||||
|
"id":"srbac",
|
||||||
|
"olxid":"4271"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Čelinac",
|
||||||
|
"id":"elinac",
|
||||||
|
"olxid":"979"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Šipovo",
|
||||||
|
"id":"ipovo",
|
||||||
|
"olxid":"4509"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Dobojsko-Bijeljinska",
|
||||||
|
"id":"dobojskobijeljinska",
|
||||||
|
"olxid": "15",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Bijeljina",
|
||||||
|
"id":"bijeljina",
|
||||||
|
"olxid":"123"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Bosanski Brod",
|
||||||
|
"id":"bosanskibrod",
|
||||||
|
"olxid":"421"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Derventa",
|
||||||
|
"id":"derventa",
|
||||||
|
"olxid":"1030"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Doboj",
|
||||||
|
"id":"doboj",
|
||||||
|
"olxid":"1088"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Donji Žabar",
|
||||||
|
"id":"donjiabar",
|
||||||
|
"olxid":"3254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Lopare",
|
||||||
|
"id":"lopare",
|
||||||
|
"olxid":"2800"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Lukavac",
|
||||||
|
"id":"lukavac",
|
||||||
|
"olxid":"6029"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Modriča",
|
||||||
|
"id":"modria",
|
||||||
|
"olxid":"2996"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Pelagićevo",
|
||||||
|
"id":"pelagievo",
|
||||||
|
"olxid":"1856"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Petrovo",
|
||||||
|
"id":"petrovo",
|
||||||
|
"olxid":"1827"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Stanari",
|
||||||
|
"id":"stanari",
|
||||||
|
"olxid":"1148"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Teslić",
|
||||||
|
"id":"tesli",
|
||||||
|
"olxid":"4549"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Tešanj",
|
||||||
|
"id":"teanj",
|
||||||
|
"olxid":"4636"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Travnik",
|
||||||
|
"id":"travnik",
|
||||||
|
"olxid":"4692"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Tuzla",
|
||||||
|
"id":"tuzla",
|
||||||
|
"olxid":"4966"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ugljevik",
|
||||||
|
"id":"ugljevik",
|
||||||
|
"olxid":"5009"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Vukosavlje",
|
||||||
|
"id":"vukosavlje",
|
||||||
|
"olxid":"3197"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Šamac",
|
||||||
|
"id":"amac",
|
||||||
|
"olxid":"539"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Sarajevsko-Zvornička",
|
||||||
|
"id":"sarajevskozvornicka",
|
||||||
|
"olxid": "16",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Bratunac",
|
||||||
|
"id":"bratunac",
|
||||||
|
"olxid":"595"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Han Pijesak",
|
||||||
|
"id":"hanpijesak",
|
||||||
|
"olxid":"1904"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ilijaš",
|
||||||
|
"id":"ilija",
|
||||||
|
"olxid":"3947"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Istočni Stari Grad",
|
||||||
|
"id":"istonistarigrad",
|
||||||
|
"olxid":"4049"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kasindo",
|
||||||
|
"id":"kasindo",
|
||||||
|
"olxid":"3880"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kladanj",
|
||||||
|
"id":"kladanj",
|
||||||
|
"olxid":"2325"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Lukavica",
|
||||||
|
"id":"lukavica",
|
||||||
|
"olxid":"3971"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Milići",
|
||||||
|
"id":"milii",
|
||||||
|
"olxid":"6143"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Olovo",
|
||||||
|
"id":"olovo",
|
||||||
|
"olxid":"3221"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Osmaci",
|
||||||
|
"id":"osmaci",
|
||||||
|
"olxid":"2128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Pale",
|
||||||
|
"id":"pale",
|
||||||
|
"olxid":"3978"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Rogatica",
|
||||||
|
"id":"rogatica",
|
||||||
|
"olxid":"3529"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Rudo",
|
||||||
|
"id":"rudo",
|
||||||
|
"olxid":"3648"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sarajevo-Novi Grad",
|
||||||
|
"id":"sarajevonovigrad",
|
||||||
|
"olxid":"6069"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Sokolac",
|
||||||
|
"id":"sokolac",
|
||||||
|
"olxid":"4183"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Srebrenica",
|
||||||
|
"id":"srebrenica",
|
||||||
|
"olxid":"4310"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Trnovo",
|
||||||
|
"id":"trnovo",
|
||||||
|
"olxid":"4067"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ustiprača",
|
||||||
|
"id":"ustipraa",
|
||||||
|
"olxid":"1593"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Višegrad",
|
||||||
|
"id":"viegrad",
|
||||||
|
"olxid":"5259"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Vlasenica",
|
||||||
|
"id":"vlasenica",
|
||||||
|
"olxid":"5456"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Zvornik",
|
||||||
|
"id":"zvornik",
|
||||||
|
"olxid":"5684"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Šekovići",
|
||||||
|
"id":"ekovii",
|
||||||
|
"olxid":"4475"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Žepa",
|
||||||
|
"id":"epa",
|
||||||
|
"olxid":"1906"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":" Trebinjsko-Fočanska",
|
||||||
|
"id":"trebinjskofocanska",
|
||||||
|
"olxid": "17",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Berkovići",
|
||||||
|
"id":"berkovii",
|
||||||
|
"olxid":"4441"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Bileća",
|
||||||
|
"id":"bilea",
|
||||||
|
"olxid":"183"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Foča",
|
||||||
|
"id":"foa",
|
||||||
|
"olxid":"1287"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Gacko",
|
||||||
|
"id":"gacko",
|
||||||
|
"olxid":"1462"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Istočni Mostar",
|
||||||
|
"id":"istonimostar",
|
||||||
|
"olxid":"3038"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Kalinovik",
|
||||||
|
"id":"kalinovik",
|
||||||
|
"olxid":"2164"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Ljubinje",
|
||||||
|
"id":"ljubinje",
|
||||||
|
"olxid":"2884"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Nevesinje",
|
||||||
|
"id":"nevesinje",
|
||||||
|
"olxid":"3138"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Trebinje",
|
||||||
|
"id":"trebinje",
|
||||||
|
"olxid":"4766"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Čajniče",
|
||||||
|
"id":"ajnie",
|
||||||
|
"olxid":"911"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Distrikt Brčko",
|
||||||
|
"id":"distriktbrcko",
|
||||||
|
"olxid": "12",
|
||||||
|
"municipalities":[
|
||||||
|
{
|
||||||
|
"name":"Brčko",
|
||||||
|
"id":"brko",
|
||||||
|
"olxid":"12"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const getRegions = () => {
|
||||||
|
return regions.map( (g) => ({ name: g.name, id: g.id, olxid: g.olxid }) );
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRegion = (regionId) => {
|
||||||
|
return regions.find(region => region.id === regionId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRegionName = (regionId) => {
|
||||||
|
const region = getRegion(regionId);
|
||||||
|
return (region && region.name) ? region.name : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMunicipalitiesForRegion = (regionId) => {
|
||||||
|
const region = getRegion(regionId);
|
||||||
|
return (region && region.municipalities) ? region.municipalities : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMunicipalityName = (regionId, municipalityId) => {
|
||||||
|
const region = getRegion(regionId);
|
||||||
|
if (!region){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const municipality = region.municipalities.find(municipality => municipality.id === municipalityId);
|
||||||
|
if (!municipality) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return municipality.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getRegions,
|
||||||
|
getRegionName,
|
||||||
|
getMunicipalitiesForRegion,
|
||||||
|
getMunicipalityName,
|
||||||
|
};
|
||||||
9
app/helpers/email.js
Normal file
9
app/helpers/email.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
const isValidEmail = (email) => {
|
||||||
|
const simpleEmailRegex = /^.+@.+\..+$/;
|
||||||
|
return (email && email.length < 250 && simpleEmailRegex.test(email));
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
isValidEmail
|
||||||
|
};
|
||||||
57
app/helpers/enums.js
Normal file
57
app/helpers/enums.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
const realEstateTypes = [
|
||||||
|
{ title: "Kuća", id: "kuca", hasGardenSize: true },
|
||||||
|
{ title: "Stan", id: "stan", hasGardenSize: false },
|
||||||
|
{ title: "Vikendica", id: "vikendica", hasGardenSize: true }
|
||||||
|
];
|
||||||
|
|
||||||
|
const sizes = [
|
||||||
|
{ title: "do 50 m2", id: "50m2" },
|
||||||
|
{ title: "do 75 m2", id: "75m2" },
|
||||||
|
{ title: "do 100 m2", id: "100m2" },
|
||||||
|
{ title: "do 150 m2", id: "150m2" },
|
||||||
|
{ title: "do 200 m2", id: "200m2" },
|
||||||
|
{ title: "preko 200 m2", id: "moreThan200m2" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const gardenSizes = [
|
||||||
|
{ title: "do 100 m2", id: "100m2" },
|
||||||
|
{ title: "do 500 m2", id: "500m2" },
|
||||||
|
{ title: "do 1 dunum", id: "1000m2" },
|
||||||
|
{ title: "do 2 dunuma", id: "2000m2" },
|
||||||
|
{ title: "do 3 dunuma", id: "3000m2" },
|
||||||
|
{ title: "preko 3 dunuma", id: "moreThan3000m2" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const prices = [
|
||||||
|
{ title: "do 50 000 KM", id: "50kKM" },
|
||||||
|
{ title: "do 100 000 KM", id: "100kKM" },
|
||||||
|
{ title: "do 150 000 KM", id: "150kKM" },
|
||||||
|
{ title: "do 200 000 KM", id: "200kKM" },
|
||||||
|
{ title: "do 250 000 KM", id: "250kKM" },
|
||||||
|
{ title: "preko 250 000 KM", id: "moreThan250kKM" }
|
||||||
|
];
|
||||||
|
|
||||||
|
const getEnumObject = (enumType, enumId) => {
|
||||||
|
return enumType.find(enumValue => enumValue.id === enumId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRealEstateTypeEnum = (enumId) => {
|
||||||
|
return getEnumObject(realEstateTypes, enumId) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getEnumTypeTitle = (enumType, enumId) => {
|
||||||
|
const enumObject = getEnumObject(enumType, enumId);
|
||||||
|
if (!enumObject){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return enumObject.title;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
realEstateTypes,
|
||||||
|
sizes,
|
||||||
|
gardenSizes,
|
||||||
|
prices,
|
||||||
|
getRealEstateTypeEnum,
|
||||||
|
getEnumTypeTitle,
|
||||||
|
};
|
||||||
13
app/helpers/url.js
Normal file
13
app/helpers/url.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
const db = require('../models/index');
|
||||||
|
|
||||||
|
const currentRERequest = async (req) => {
|
||||||
|
const uniqueId = req.params['request_id'];
|
||||||
|
if(!uniqueId) return null;
|
||||||
|
|
||||||
|
const request = await db.RealEstateRequest.findOne({ where: {uniqueId} });
|
||||||
|
return request;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
currentRERequest
|
||||||
|
};
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
const convertToDate = require("./convertToDate");
|
const convertToDate = require("./convertToDate");
|
||||||
|
|
||||||
function areThereAnyNewItems(lastItemDate, controlDate) {
|
function areThereAnyNewItems(lastItemDate, controlDate) {
|
||||||
if (!lastItemDate) {
|
if (!lastItemDate) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return new Date(controlDate) < convertToDate(lastItemDate);
|
return new Date(controlDate) < convertToDate(lastItemDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = areThereAnyNewItems;
|
module.exports = areThereAnyNewItems;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
let fetch = require("node-fetch");
|
let fetch = require("node-fetch");
|
||||||
let cheerio = require("cheerio");
|
let cheerio = require("cheerio");
|
||||||
const areThereAnyNewItems = require("./arethereanynewitems");
|
const areThereAnyNewItems = require("./areThereAnyNewItems");
|
||||||
|
|
||||||
async function scrapTheItems(url, controlDate, noNewItems = false) {
|
async function scrapTheItems(url, controlDate, noNewItems = false) {
|
||||||
let items = [];
|
let items = [];
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
const scrapTheItems = require("./scraptheitems");
|
const scrapTheItems = require("./scrapTheItems");
|
||||||
const convertToDate = require("./convertToDate");
|
const convertToDate = require("./convertToDate");
|
||||||
const AWS = require('aws-sdk');
|
const AWS = require('aws-sdk');
|
||||||
AWS.config.update({region: 'eu-central-1'});
|
AWS.config.update({region: 'eu-central-1'});
|
||||||
|
|
||||||
|
|
||||||
async function sendNotification(marketAlert) {
|
async function sendNotification(marketAlert) {
|
||||||
const { id, email, olx_url, last_date } = marketAlert;
|
const { id, email, olx_url } = marketAlert;
|
||||||
let url =
|
let url =
|
||||||
"https://www.olx.ba/pretraga?" + olx_url + "&sort_order=desc&sort_po=datum";
|
"https://www.olx.ba/pretraga?" + olx_url + "&sort_order=desc&sort_po=datum";
|
||||||
let newItems = await scrapTheItems(url);
|
let newItems = await scrapTheItems(url);
|
||||||
@@ -17,8 +17,8 @@ async function sendNotification(marketAlert) {
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create sendEmail params
|
// Create sendEmail params
|
||||||
var params = {
|
const params = {
|
||||||
Destination: { /* required */
|
Destination: { /* required */
|
||||||
CcAddresses: [
|
CcAddresses: [
|
||||||
],
|
],
|
||||||
@@ -50,7 +50,7 @@ async function sendNotification(marketAlert) {
|
|||||||
|
|
||||||
if (message) {
|
if (message) {
|
||||||
const sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();
|
const sendPromise = new AWS.SES({apiVersion: '2010-12-01'}).sendEmail(params).promise();
|
||||||
await sendPromise;
|
await sendPromise;
|
||||||
return { id, date: String(convertToDate(lastDate)) };
|
return { id, date: String(convertToDate(lastDate)) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
34
app/migrations/20190417035319-create-market-alert.js
Normal file
34
app/migrations/20190417035319-create-market-alert.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
'use strict';
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('MarketAlerts', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
olxUrl: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
lastDate: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: Sequelize.STRING,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('MarketAlerts');
|
||||||
|
}
|
||||||
|
};
|
||||||
33
app/migrations/20190417035707-create-real-estate-request.js
Normal file
33
app/migrations/20190417035707-create-real-estate-request.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
'use strict';
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.createTable('RealEstateRequests', {
|
||||||
|
id: {
|
||||||
|
allowNull: false,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
type: Sequelize.INTEGER
|
||||||
|
},
|
||||||
|
uniqueId: {
|
||||||
|
type: Sequelize.UUID
|
||||||
|
},
|
||||||
|
realEstateType: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
email: {
|
||||||
|
type: Sequelize.STRING
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
allowNull: false,
|
||||||
|
type: Sequelize.DATE
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.dropTable('RealEstateRequests');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.addColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'city',
|
||||||
|
Sequelize.STRING
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.removeColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'city'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.addColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'place',
|
||||||
|
Sequelize.STRING
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.removeColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'place'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
19
app/migrations/20190516180226-rename-place-column.js
Normal file
19
app/migrations/20190516180226-rename-place-column.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.renameColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'place',
|
||||||
|
'municipality'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.renameColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'municipality',
|
||||||
|
'place'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
19
app/migrations/20190516222240-rename-city-column.js
Normal file
19
app/migrations/20190516222240-rename-city-column.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.renameColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'city',
|
||||||
|
'region'
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.renameColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'region',
|
||||||
|
'city'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.addColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'size',
|
||||||
|
{
|
||||||
|
type: Sequelize.STRING
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.removeColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'size'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.addColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'gardenSize',
|
||||||
|
{
|
||||||
|
type: Sequelize.STRING
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.removeColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'gardenSize'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.addColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'price',
|
||||||
|
{
|
||||||
|
type: Sequelize.STRING
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.removeColumn(
|
||||||
|
'RealEstateRequests',
|
||||||
|
'price'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
15
app/migrations/20190523144812-activate-postgis.js
Normal file
15
app/migrations/20190523144812-activate-postgis.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.sequelize.query("CREATE EXTENSION postgis").then(([results, metadata]) => {
|
||||||
|
/// No result
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.sequelize.query("DROP EXTENSION IF EXISTS postgis").then(([results, metadata]) => {
|
||||||
|
/// No result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
17
app/migrations/20190523151420-add-bounding-box-column.js
Normal file
17
app/migrations/20190523151420-add-bounding-box-column.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
up: (queryInterface, Sequelize) => {
|
||||||
|
|
||||||
|
return queryInterface.sequelize.query("ALTER TABLE \"RealEstateRequests\" ADD COLUMN bounding_box geometry(Polygon);").then(([results, metadata]) => {
|
||||||
|
/// No result
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
down: (queryInterface, Sequelize) => {
|
||||||
|
return queryInterface.sequelize.query("ALTER TABLE \"RealEstateRequests\" DROP COLUMN bounding_box").then(([results, metadata]) => {
|
||||||
|
/// No result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const Sequelize = require("sequelize");
|
|
||||||
const sequelize = require("../db/db");
|
|
||||||
const MarketAlert = sequelize.define("market_alert", {
|
|
||||||
id: {
|
|
||||||
type: Sequelize.INTEGER,
|
|
||||||
autoIncrement: true,
|
|
||||||
primaryKey: true
|
|
||||||
},
|
|
||||||
olx_url: Sequelize.STRING,
|
|
||||||
last_date: Sequelize.STRING,
|
|
||||||
email: {
|
|
||||||
type: Sequelize.STRING,
|
|
||||||
allowNull: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = MarketAlert;
|
|
||||||
37
app/models/index.js
Normal file
37
app/models/index.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const Sequelize = require('sequelize');
|
||||||
|
const basename = path.basename(__filename);
|
||||||
|
const env = process.env.NODE_ENV || 'development';
|
||||||
|
const config = require(__dirname + '/../config/config.json')[env];
|
||||||
|
const db = {};
|
||||||
|
|
||||||
|
let sequelize;
|
||||||
|
if (config.use_env_variable) {
|
||||||
|
sequelize = new Sequelize(process.env[config.use_env_variable], config);
|
||||||
|
} else {
|
||||||
|
sequelize = new Sequelize(config.database, config.username, config.password, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs
|
||||||
|
.readdirSync(__dirname)
|
||||||
|
.filter(file => {
|
||||||
|
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
|
||||||
|
})
|
||||||
|
.forEach(file => {
|
||||||
|
const model = sequelize['import'](path.join(__dirname, file));
|
||||||
|
db[model.name] = model;
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.keys(db).forEach(modelName => {
|
||||||
|
if (db[modelName].associate) {
|
||||||
|
db[modelName].associate(db);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
db.sequelize = sequelize;
|
||||||
|
db.Sequelize = Sequelize;
|
||||||
|
|
||||||
|
module.exports = db;
|
||||||
15
app/models/marketalert.js
Normal file
15
app/models/marketalert.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
'use strict';
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const MarketAlert = sequelize.define('MarketAlert', {
|
||||||
|
olxUrl: DataTypes.STRING,
|
||||||
|
lastDate: DataTypes.STRING,
|
||||||
|
email: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNul: false
|
||||||
|
}
|
||||||
|
}, {});
|
||||||
|
MarketAlert.associate = function(models) {
|
||||||
|
// associations can be defined here
|
||||||
|
};
|
||||||
|
return MarketAlert;
|
||||||
|
};
|
||||||
24
app/models/realestaterequest.js
Normal file
24
app/models/realestaterequest.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
|
||||||
|
const RealEstateRequest = sequelize.define('RealEstateRequest', {
|
||||||
|
uniqueId: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
allowNull: false
|
||||||
|
},
|
||||||
|
realEstateType: DataTypes.STRING,
|
||||||
|
email: DataTypes.STRING,
|
||||||
|
region: DataTypes.STRING,
|
||||||
|
municipality: DataTypes.STRING,
|
||||||
|
size: DataTypes.STRING,
|
||||||
|
gardenSize: DataTypes.STRING,
|
||||||
|
price: DataTypes.STRING,
|
||||||
|
bounding_box: DataTypes.GEOMETRY('POINT', 4326)
|
||||||
|
}, {});
|
||||||
|
RealEstateRequest.associate = function(models) {
|
||||||
|
// associations can be defined here
|
||||||
|
};
|
||||||
|
return RealEstateRequest;
|
||||||
|
};
|
||||||
BIN
app/public/images/logo.png
Normal file
BIN
app/public/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
36
app/public/main.css
Normal file
36
app/public/main.css
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
.welcome-center-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-big-logo {
|
||||||
|
font-size: 200pt;
|
||||||
|
background-image: url(./images/logo.png);
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#map {
|
||||||
|
height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#floating-panel {
|
||||||
|
top: 10px;
|
||||||
|
left: 25%;
|
||||||
|
z-index: 5;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #999;
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Roboto', 'sans-serif';
|
||||||
|
line-height: 30px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
<a href="<%= nextStep %>"><button>Kreni</button></a>
|
|
||||||
|
|
||||||
29
app/views/gardenSize.ejs
Normal file
29
app/views/gardenSize.ejs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>Koliko okućnice tražite ?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-gardensize">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const gardenSize of gardenSizes) { %>
|
||||||
|
<li class="collection-item" >
|
||||||
|
<div id="<%= gardenSize.id %>" onclick="saveAndSubmit(this.id)"><%= gardenSize.title %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="gardensize" id="gardensize" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id) {
|
||||||
|
$("#gardensize").val(id);
|
||||||
|
$("#form-gardensize").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
25
app/views/goAgain.ejs
Normal file
25
app/views/goAgain.ejs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h4>Provjerite Vaš email !</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row center-align">
|
||||||
|
<h4>Želite li pretražiti još jednu nekretninu ?</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-goagain">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s3 push-s3">
|
||||||
|
<a href="/" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
Da
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col s3 push-s3">
|
||||||
|
<a href="/" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
Ne
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
<!doctype>
|
<!doctype>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||||
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="stylesheet" href="/assets/main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
Something in your body:
|
<div class="container">
|
||||||
|
<%-body%>
|
||||||
|
</div>
|
||||||
<%-body%>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
28
app/views/municipality.ejs
Normal file
28
app/views/municipality.ejs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>U kojem mjestu tražite nekretninu?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-municipality">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const municipality of municipalities) { %>
|
||||||
|
<li class="collection-item">
|
||||||
|
<div val="<%= municipality.name %>" id="<%= municipality.id %>" onclick="saveAndSubmit(this.id)"><%= municipality.name %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="municipality" id="municipality" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id, name) {
|
||||||
|
$("#municipality").val(id);
|
||||||
|
$("#form-municipality").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
90
app/views/neighborhoodMap.ejs
Normal file
90
app/views/neighborhoodMap.ejs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<div class="row center-align">
|
||||||
|
<h2>U kojem naselju tražite nekretninu?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row center-align" >
|
||||||
|
<div id="floating-panel">
|
||||||
|
<input id="address" type="textbox" value="">
|
||||||
|
<input id="submit" type="button" value="Trazi">
|
||||||
|
</div>
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
|
<form method="POST" id="form-map-output">
|
||||||
|
<div class="row center-align">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<a id="btnsubmit" href="#" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
Dalje
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="north" id=north />
|
||||||
|
<input type="hidden" name="south" id=south />
|
||||||
|
<input type="hidden" name="east" id=east />
|
||||||
|
<input type="hidden" name="west" id=west />
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
var map;
|
||||||
|
var municipality = "<%= municipality%>";
|
||||||
|
var defaultAddress = document.getElementById('address');
|
||||||
|
|
||||||
|
var BOSNIA_BOUNDS = {
|
||||||
|
north: 45.70,
|
||||||
|
south: 41.69,
|
||||||
|
west: 15.55,
|
||||||
|
east: 20.77,
|
||||||
|
};
|
||||||
|
|
||||||
|
function initMap() {
|
||||||
|
map = new google.maps.Map(document.getElementById('map'), {
|
||||||
|
center: { lat: -34.397, lng: 150.644 },
|
||||||
|
zoom: 11,
|
||||||
|
restriction: {
|
||||||
|
latLngBounds: BOSNIA_BOUNDS,
|
||||||
|
strictBounds: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
var geocoder = new google.maps.Geocoder();
|
||||||
|
|
||||||
|
document.getElementById('submit').addEventListener('click', function () {
|
||||||
|
geocodeAddress(geocoder, map);
|
||||||
|
});
|
||||||
|
|
||||||
|
function geocodeAddress(geocoder, resultsMap) {
|
||||||
|
var address = document.getElementById('address').value;
|
||||||
|
geocoder.geocode({ 'address': address }, function (results, status) {
|
||||||
|
if (status === 'OK') {
|
||||||
|
resultsMap.setCenter(results[0].geometry.location);
|
||||||
|
var marker = new google.maps.Marker({
|
||||||
|
map: resultsMap,
|
||||||
|
position: results[0].geometry.location
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert('Geocode was not successful for the following reason: ' + status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultAddress.value = municipality;
|
||||||
|
geocodeAddress(geocoder, map);
|
||||||
|
|
||||||
|
$(document).ready(() => {
|
||||||
|
$("#btnsubmit").click(() => {
|
||||||
|
var bounds = map.getBounds();
|
||||||
|
|
||||||
|
$("#north").val(bounds.na.l);
|
||||||
|
$("#south").val(bounds.na.j);
|
||||||
|
$("#east").val(bounds.ia.l);
|
||||||
|
$("#west").val(bounds.ia.j);
|
||||||
|
|
||||||
|
$("#form-map-output").submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAna8ohfV2HBMcxGk_29vqxU5Z_bDickqg&callback=initMap"
|
||||||
|
async defer></script>
|
||||||
|
</div>
|
||||||
29
app/views/price.ejs
Normal file
29
app/views/price.ejs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>Koja Vam okvirna cijena odgovara ?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-price">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const price of prices) { %>
|
||||||
|
<li class="collection-item" >
|
||||||
|
<div id="<%= price.id %>" onclick="saveAndSubmit(this.id)"><%= price.title %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="price" id="price" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id) {
|
||||||
|
$("#price").val(id);
|
||||||
|
$("#form-price").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
36
app/views/queryReview.ejs
Normal file
36
app/views/queryReview.ejs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>Da li je ovo to što ste tražili ?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-queryreview">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const stepData of queryData) { %>
|
||||||
|
<li class="collection-item" >
|
||||||
|
<div id="<%= stepData.id %>" ><%= stepData.title || '-' %>
|
||||||
|
<a href="<%= stepData.url %>" class="secondary-content">
|
||||||
|
<i class="material-icons">edit</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<a id="submit" href="#" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
To je to
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready( () => {
|
||||||
|
$("#submit").click( () => {
|
||||||
|
$("#form-queryreview").submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
43
app/views/querySubmit.ejs
Normal file
43
app/views/querySubmit.ejs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h4>Da Vam javimo kada se Vaša željena nekretnina pojavi u oglasima, upišite svoj e-mail</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-submitquery">
|
||||||
|
<div class="row center-align">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<input id="email" name="email" type="email" placeholder="vas.email@mail.com" required size="250" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<% if (error) {%>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<h6 style="color: red">Greška ! Unesite ispravan email</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%}%>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<a id="submit" href="#" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
Javi mi
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<p>* U svakom trenutku možete prekinuti slanje objava kroz link u e-mailu</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready( () => {
|
||||||
|
$("#submit").click( () => {
|
||||||
|
const emailField = document.getElementById('email');
|
||||||
|
if (emailField.validity.valid){
|
||||||
|
$("#form-submitquery").submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
33
app/views/realEstateType.ejs
Normal file
33
app/views/realEstateType.ejs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>Koju nekretninu tražite?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-real-estate-type">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const realEstateType of realEstateTypes) { %>
|
||||||
|
<li class="collection-item">
|
||||||
|
<div id="<%= realEstateType.id %>" onclick="saveAndSubmit(this.id)"><%= realEstateType.title %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="realestatetype" id="realestatetype" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id) {
|
||||||
|
$("#realestatetype").val(id);
|
||||||
|
$("#form-real-estate-type").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
29
app/views/region.ejs
Normal file
29
app/views/region.ejs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>U kojoj regiji tražite nekretninu?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-region">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const region of regions) { %>
|
||||||
|
<li class="collection-item">
|
||||||
|
<div id="<%= region.id %>" onclick="saveAndSubmit(this.id)"><%= region.name %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="region" id="region" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id) {
|
||||||
|
$("#region").val(id);
|
||||||
|
$("#form-region").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
29
app/views/size.ejs
Normal file
29
app/views/size.ejs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<!--suppress HtmlUnknownAnchorTarget -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<h2>Do koliko kvadrata tražite nekretninu ?</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" id="form-size">
|
||||||
|
<div class="row center-align">
|
||||||
|
<ul class="collection with-header">
|
||||||
|
<% for(const size of sizes) { %>
|
||||||
|
<li class="collection-item">
|
||||||
|
<div id="<%= size.id %>" onclick="saveAndSubmit(this.id)"><%= size.title %>
|
||||||
|
<a href="#" class="secondary-content">
|
||||||
|
<i class="material-icons">send</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="size" id="size" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function saveAndSubmit(id) {
|
||||||
|
$("#size").val(id);
|
||||||
|
$("#form-size").submit();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
<a href="<%= nextStep %>"> >>> </a>
|
|
||||||
|
|
||||||
17
app/views/welcome.ejs
Normal file
17
app/views/welcome.ejs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
<!-- -->
|
||||||
|
<div class="row center-align">
|
||||||
|
<span class="welcome-big-logo">🤙</span>
|
||||||
|
</div>
|
||||||
|
<div class="row center-align">
|
||||||
|
<div>Sve nekretnine dostupne u oglasima.</div>
|
||||||
|
<div> Na vaš email. </div>
|
||||||
|
<div> BESPLATNO </div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col s6 push-s3">
|
||||||
|
<a href="<%= nextStep %>" class="welcome-center-button waves-effect waves-light btn">
|
||||||
|
Javi mi
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
73
index.js
73
index.js
@@ -1,13 +1,22 @@
|
|||||||
const dobrodosli = require('./app/controllers/dobrodosli').getDobrodosli;
|
const welcome = require('./app/controllers/welcome').getWelcome;
|
||||||
const getVrstaNekretnine = require('./app/controllers/vrsta_nekretnine').getVrstaNekretnine;
|
const { getRealEstateTypes, postRealEstateTypes} = require('./app/controllers/realEstateTypes');
|
||||||
|
const { getRegion, postRegion } = require('./app/controllers/regions');
|
||||||
|
const { getMunicipality, postMunicipality } = require('./app/controllers/municipalities');
|
||||||
|
const { getSize, postSize } = require('./app/controllers/sizes');
|
||||||
|
const { getGardenSize, postGardenSize } = require('./app/controllers/gardenSizes');
|
||||||
|
const { getPrice, postPrice } = require('./app/controllers/prices');
|
||||||
|
const { getQueryReview, postQueryReview } = require('./app/controllers/queryReview');
|
||||||
|
const { getQuerySubmit, postQuerySubmit } = require('./app/controllers/querySubmit');
|
||||||
|
const { getGoAgain } = require('./app/controllers/goAgain');
|
||||||
|
const { getNeighborhood, postNeighborhood } = require('./app/controllers/neighborhoodMap');
|
||||||
|
|
||||||
let express = require("express");
|
let express = require("express");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const bodyParser = require("body-parser");
|
const bodyParser = require("body-parser");
|
||||||
const MarketAlert = require("./app/models/MarketAlert");
|
const MarketAlert = require("./app/models/marketalert");
|
||||||
const sendNotification = require("./app/lib/sendnotification");
|
const sendNotification = require("./app/lib/sendNotification");
|
||||||
const scrapTheItems = require("./app/lib/scraptheitems");
|
const scrapTheItems = require("./app/lib/scrapTheItems");
|
||||||
const sequelize = require("./app/db/db");
|
const sequelize = require("./app/models/index").sequelize;
|
||||||
const Twocheckout = require("2checkout-node");
|
const Twocheckout = require("2checkout-node");
|
||||||
const layout = require('express-layout');
|
const layout = require('express-layout');
|
||||||
|
|
||||||
@@ -21,8 +30,10 @@ app.set('views', path.join(__dirname, '/app/views'));
|
|||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
app.use(layout());
|
app.use(layout());
|
||||||
|
|
||||||
|
const compression = require('compression');
|
||||||
|
app.use(compression());
|
||||||
|
|
||||||
app.get("/api/sendnotifications", async function(req, res) {
|
app.get("/api/sendnotifications", async (req, res) => {
|
||||||
let marketAlerts = await MarketAlert.findAll();
|
let marketAlerts = await MarketAlert.findAll();
|
||||||
|
|
||||||
let lastDateUpdate = await Promise.all(
|
let lastDateUpdate = await Promise.all(
|
||||||
@@ -55,7 +66,7 @@ app.get("/api/items/:url", async (req, res) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/marketalerts", function(req, res) {
|
app.post("/api/marketalerts", (req, res) => {
|
||||||
const { email, last_date, olx_url } = req.body;
|
const { email, last_date, olx_url } = req.body;
|
||||||
console.log(email, last_date, olx_url);
|
console.log(email, last_date, olx_url);
|
||||||
sequelize.sync().then(() => {
|
sequelize.sync().then(() => {
|
||||||
@@ -71,7 +82,7 @@ app.post("/api/marketalerts", function(req, res) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/payforalert", function(request, response) {
|
app.post("/api/payforalert", (req, res) => {
|
||||||
let tco = new Twocheckout({
|
let tco = new Twocheckout({
|
||||||
sellerId: "901402692",
|
sellerId: "901402692",
|
||||||
privateKey: "A28DCE5F-9292-405C-8161-F84D8BB83AFC",
|
privateKey: "A28DCE5F-9292-405C-8161-F84D8BB83AFC",
|
||||||
@@ -80,7 +91,7 @@ app.post("/api/payforalert", function(request, response) {
|
|||||||
|
|
||||||
let params = {
|
let params = {
|
||||||
merchantOrderId: "123",
|
merchantOrderId: "123",
|
||||||
token: request.body.token,
|
token: req.body.token,
|
||||||
currency: "USD",
|
currency: "USD",
|
||||||
total: "2.00",
|
total: "2.00",
|
||||||
billingAddr: {
|
billingAddr: {
|
||||||
@@ -90,21 +101,53 @@ app.post("/api/payforalert", function(request, response) {
|
|||||||
state: "BiH",
|
state: "BiH",
|
||||||
zipCode: "71000",
|
zipCode: "71000",
|
||||||
country: "BiH",
|
country: "BiH",
|
||||||
email: request.body.email,
|
email: req.body.email,
|
||||||
phoneNumber: "5555555555"
|
phoneNumber: "5555555555"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tco.checkout.authorize(params, function(error, data) {
|
tco.checkout.authorize(params, function(error, data) {
|
||||||
if (error) {
|
if (error) {
|
||||||
response.send(error.message);
|
res.send(error.message);
|
||||||
} else {
|
} else {
|
||||||
response.send(data.response.responseMsg);
|
res.send(data.response.responseMsg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/', dobrodosli);
|
app.get('/', welcome);
|
||||||
app.get('/vrstanekretnine', getVrstaNekretnine);
|
app.get('/vrstanekretnine/:request_id', getRealEstateTypes);
|
||||||
|
app.get('/vrstanekretnine', getRealEstateTypes);
|
||||||
|
|
||||||
|
app.post('/vrstanekretnine/:request_id', postRealEstateTypes);
|
||||||
|
app.post('/vrstanekretnine', postRealEstateTypes);
|
||||||
|
|
||||||
|
app.get('/grad/:request_id', getRegion);
|
||||||
|
app.post('/grad/:request_id', postRegion);
|
||||||
|
|
||||||
|
app.get('/mjesto/:request_id', getMunicipality);
|
||||||
|
app.post('/mjesto/:request_id', postMunicipality);
|
||||||
|
|
||||||
|
app.get('/naselje/:request_id/:municipality', getNeighborhood);
|
||||||
|
app.post('/naselje/:request_id/:municipality', postNeighborhood);
|
||||||
|
|
||||||
|
app.get('/povrsina/:request_id', getSize);
|
||||||
|
app.post('/povrsina/:request_id', postSize);
|
||||||
|
|
||||||
|
app.get('/okucnica/:request_id', getGardenSize);
|
||||||
|
app.post('/okucnica/:request_id', postGardenSize);
|
||||||
|
|
||||||
|
app.get('/cijena/:request_id', getPrice);
|
||||||
|
app.post('/cijena/:request_id', postPrice);
|
||||||
|
|
||||||
|
app.get('/pregled/:request_id', getQueryReview);
|
||||||
|
app.post('/pregled/:request_id', postQueryReview);
|
||||||
|
|
||||||
|
app.get('/posalji/:request_id', getQuerySubmit);
|
||||||
|
app.post('/posalji/:request_id', postQuerySubmit);
|
||||||
|
|
||||||
|
app.get('/ponovo', getGoAgain);
|
||||||
|
|
||||||
|
app.use('/assets', express.static('./app/public'));
|
||||||
|
|
||||||
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
|
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
|
||||||
|
|||||||
3176
package-lock.json
generated
3176
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -6,7 +6,11 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "node ./index.js",
|
"start": "node ./index.js",
|
||||||
"heroku-postbuild": "cd frontend-react && npm install && npm run build"
|
"start-mon": "nodemon ./index.js",
|
||||||
|
"migrate": "cd app && npx sequelize db:migrate",
|
||||||
|
"setup": "docker build -t marketalerts . && docker run -e POSTGRES_USER=docker -e POSTGRES_PASSWORD=docker -e POSTGRES_DB=marketalerts --name pg_marketalerts -d -p 5432:5432 marketalerts && sleep 4 && npm run migrate",
|
||||||
|
"docker-start": "docker start pg_marketalerts",
|
||||||
|
"docker-stop": "docker stop pg_marketalerts"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -22,13 +26,19 @@
|
|||||||
"@sendgrid/mail": "^6.3.1",
|
"@sendgrid/mail": "^6.3.1",
|
||||||
"aws-sdk": "^2.422.0",
|
"aws-sdk": "^2.422.0",
|
||||||
"cheerio": "^1.0.0-rc.2",
|
"cheerio": "^1.0.0-rc.2",
|
||||||
|
"compression": "^1.7.4",
|
||||||
|
"dotenv": "^7.0.0",
|
||||||
"ejs": "^2.6.1",
|
"ejs": "^2.6.1",
|
||||||
"express": "^4.16.4",
|
"express": "^4.16.4",
|
||||||
"express-ejs-layouts": "^2.5.0",
|
"express-ejs-layouts": "^2.5.0",
|
||||||
"express-layout": "^0.1.0",
|
"express-layout": "^0.1.0",
|
||||||
"mysql2": "^1.6.4",
|
|
||||||
"node-fetch": "^2.3.0",
|
"node-fetch": "^2.3.0",
|
||||||
|
"pg": "^7.10.0",
|
||||||
"react-step-wizard": "^5.1.0",
|
"react-step-wizard": "^5.1.0",
|
||||||
"sequelize": "^4.42.0"
|
"sequelize": "^4.43.2",
|
||||||
|
"sequelize-cli": "^5.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^1.19.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
389
tools/kantoni.html
Normal file
389
tools/kantoni.html
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
<!DOCTYPE>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.4.0.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<select name="kanton" id="kanton" class="drop-select" onchange="pronadji_gradove()">
|
||||||
|
<option value="">Iz svih lokacija</option>
|
||||||
|
|
||||||
|
<option value="" disabled="">Federacija BiH</option>
|
||||||
|
<option value="9"> Sarajevo</option>
|
||||||
|
<option value="3"> Tuzlanski</option>
|
||||||
|
<option value="4"> Zeničko-Dobojski</option>
|
||||||
|
<option value="1"> Unsko-Sanski</option>
|
||||||
|
<option value="2"> Posavski</option>
|
||||||
|
<option value="5"> Bosansko-podrinjski</option>
|
||||||
|
<option value="6"> Srednjobosanski</option>
|
||||||
|
<option value="7"> Hercegovačko-Neretvanski</option>
|
||||||
|
<option value="8"> Zapadno-Hercegovački</option>
|
||||||
|
<option value="10"> Livanjski</option>
|
||||||
|
|
||||||
|
<option value="" disabled="">Republika Srpska</option>
|
||||||
|
<option value="14"> Banjalučka</option>
|
||||||
|
<option value="15"> Dobojsko-Bijeljinska</option>
|
||||||
|
<option value="16"> Sarajevsko-Zvornička</option>
|
||||||
|
<option value="17"> Trebinjsko-Fočanska</option>
|
||||||
|
|
||||||
|
<option value="12">Disktrikt Brčko</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="unskosanski" id="unskosanski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="75">Bihać</option>
|
||||||
|
<option value="373">Bosanska Krupa</option>
|
||||||
|
<option value="504">Bosanski Petrovac</option>
|
||||||
|
<option value="374">Bužim</option>
|
||||||
|
<option value="857">Cazin</option>
|
||||||
|
<option value="2362">Ključ</option>
|
||||||
|
<option value="3738">Sanski Most</option>
|
||||||
|
<option value="5122">Velika Kladuša</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="posavski" id="posavski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="6144">Domaljevac</option>
|
||||||
|
<option value="424">Odžak</option>
|
||||||
|
<option value="3252">Orašje</option>
|
||||||
|
<option value="540">Šamac</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="tuzlanski" id="tuzlanski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="2">Banovići</option>
|
||||||
|
<option value="1090">Doboj-Istok</option>
|
||||||
|
<option value="1854">Gradačac</option>
|
||||||
|
<option value="1826">Gračanica</option>
|
||||||
|
<option value="2129">Kalesija</option>
|
||||||
|
<option value="2319">Kladanj</option>
|
||||||
|
<option value="2840">Lukavac</option>
|
||||||
|
<option value="5699">Sapna</option>
|
||||||
|
<option value="4391">Srebrenik</option>
|
||||||
|
<option value="5010">Teočak</option>
|
||||||
|
<option value="4944">Tuzla</option>
|
||||||
|
<option value="2801">Čelić</option>
|
||||||
|
<option value="5774">Živinice</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="zenickodobojski" id="zenickodobojski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="704">Breza</option>
|
||||||
|
<option value="1122">Doboj-Jug</option>
|
||||||
|
<option value="2022">Kakanj</option>
|
||||||
|
<option value="2941">Maglaj</option>
|
||||||
|
<option value="1925">Olovo</option>
|
||||||
|
<option value="4594">Tešanj</option>
|
||||||
|
<option value="1087">Usora</option>
|
||||||
|
<option value="5037">Vareš</option>
|
||||||
|
<option value="5171">Visoko</option>
|
||||||
|
<option value="5548">Zavidovići</option>
|
||||||
|
<option value="4571">Zenica</option>
|
||||||
|
<option value="2940">Žepče</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="bosanskopodrinjski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="1289">Foča</option>
|
||||||
|
<option value="1588">Goražde</option>
|
||||||
|
<option value="3546">Pale</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="srednjobosanski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="732">Bugojno</option>
|
||||||
|
<option value="810">Busovača</option>
|
||||||
|
<option value="4151">Dobretići</option>
|
||||||
|
<option value="1160">Donji Vakuf</option>
|
||||||
|
<option value="1407">Fojnica</option>
|
||||||
|
<option value="1775">Gornji Vakuf - Uskoplje</option>
|
||||||
|
<option value="1960">Jajce</option>
|
||||||
|
<option value="2237">Kiseljak</option>
|
||||||
|
<option value="2608">Kreševo</option>
|
||||||
|
<option value="3477">Novi Travnik</option>
|
||||||
|
<option value="4678">Travnik</option>
|
||||||
|
<option value="5422">Vitez</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="hercegovackoneretvanski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="3017">Grad Mostar</option>
|
||||||
|
<option value="1930">Jablanica</option>
|
||||||
|
<option value="2169">Konjic</option>
|
||||||
|
<option value="3111">Neum</option>
|
||||||
|
<option value="3421">Prozor</option>
|
||||||
|
<option value="4769">Ravno</option>
|
||||||
|
<option value="4439">Stolac</option>
|
||||||
|
<option value="947">Čapljina</option>
|
||||||
|
<option value="1009">Čitluk</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="zapadnohercegovacki" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="1892">Grude</option>
|
||||||
|
<option value="2905">Ljubuški</option>
|
||||||
|
<option value="3268">Posušje</option>
|
||||||
|
<option value="2708">Široki Brijeg</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="sarajevo" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="3817">Hadžići</option>
|
||||||
|
<option value="3879">Ilidža</option>
|
||||||
|
<option value="3892">Ilijaš</option>
|
||||||
|
<option value="3812">Sarajevo - Centar</option>
|
||||||
|
<option value="3969">Sarajevo-Novi Grad</option>
|
||||||
|
<option value="5896">Sarajevo-Novo Sarajevo</option>
|
||||||
|
<option value="4048">Sarajevo-Stari Grad</option>
|
||||||
|
<option value="4063">Trnovo</option>
|
||||||
|
<option value="4126">Vogošća</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="livanjski" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="560">Bosansko Grahovo</option>
|
||||||
|
<option value="4640">Drvar</option>
|
||||||
|
<option value="1533">Glamoč</option>
|
||||||
|
<option value="2635">Kupres</option>
|
||||||
|
<option value="2741">Livno</option>
|
||||||
|
<option value="1228">Tomislavgrad</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="grad11" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="645">distriktbrcko</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="banjalučka" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="21">Banja Luka</option>
|
||||||
|
<option value="305">Gradiška</option>
|
||||||
|
<option value="4662">Istočni Drvar</option>
|
||||||
|
<option value="1965">Jezero</option>
|
||||||
|
<option value="4147">Kneževo</option>
|
||||||
|
<option value="6142">Kostajnica</option>
|
||||||
|
<option value="2574">Kotor Varoš</option>
|
||||||
|
<option value="244">Kozarska Dubica</option>
|
||||||
|
<option value="382">Krupa na uni</option>
|
||||||
|
<option value="2654">Kupres </option>
|
||||||
|
<option value="2671">Laktaši</option>
|
||||||
|
<option value="3073">Mrkonjić Grad</option>
|
||||||
|
<option value="444">Novi Grad</option>
|
||||||
|
<option value="3737">Oštra Luka</option>
|
||||||
|
<option value="515">Petrovac</option>
|
||||||
|
<option value="3287">Prijedor</option>
|
||||||
|
<option value="3358">Prnjavor</option>
|
||||||
|
<option value="2365">Ribnik</option>
|
||||||
|
<option value="4271">Srbac</option>
|
||||||
|
<option value="979">Čelinac</option>
|
||||||
|
<option value="4509">Šipovo</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="dobojskobijeljinska" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="123">Bijeljina</option>
|
||||||
|
<option value="421">Bosanski Brod</option>
|
||||||
|
<option value="1030">Derventa</option>
|
||||||
|
<option value="1088">Doboj</option>
|
||||||
|
<option value="3254">Donji Žabar</option>
|
||||||
|
<option value="2800">Lopare</option>
|
||||||
|
<option value="6029">Lukavac</option>
|
||||||
|
<option value="2996">Modriča</option>
|
||||||
|
<option value="1856">Pelagićevo</option>
|
||||||
|
<option value="1827">Petrovo</option>
|
||||||
|
<option value="1148">Stanari</option>
|
||||||
|
<option value="4549">Teslić</option>
|
||||||
|
<option value="4636">Tešanj</option>
|
||||||
|
<option value="4692">Travnik</option>
|
||||||
|
<option value="4966">Tuzla</option>
|
||||||
|
<option value="5009">Ugljevik</option>
|
||||||
|
<option value="3197">Vukosavlje</option>
|
||||||
|
<option value="539">Šamac</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="sarajevskozvornicka" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="595">Bratunac</option>
|
||||||
|
<option value="1904">Han Pijesak</option>
|
||||||
|
<option value="3947">Ilijaš</option>
|
||||||
|
<option value="4049">Istočni Stari Grad</option>
|
||||||
|
<option value="3880">Kasindo</option>
|
||||||
|
<option value="2325">Kladanj</option>
|
||||||
|
<option value="3971">Lukavica</option>
|
||||||
|
<option value="6143">Milići</option>
|
||||||
|
<option value="3221">Olovo</option>
|
||||||
|
<option value="2128">Osmaci</option>
|
||||||
|
<option value="3978">Pale</option>
|
||||||
|
<option value="3529">Rogatica</option>
|
||||||
|
<option value="3648">Rudo</option>
|
||||||
|
<option value="6069">Sarajevo-Novi Grad</option>
|
||||||
|
<option value="4183">Sokolac</option>
|
||||||
|
<option value="4310">Srebrenica</option>
|
||||||
|
<option value="4067">Trnovo</option>
|
||||||
|
<option value="1593">Ustiprača</option>
|
||||||
|
<option value="5259">Višegrad</option>
|
||||||
|
<option value="5456">Vlasenica</option>
|
||||||
|
<option value="5684">Zvornik</option>
|
||||||
|
<option value="4475">Šekovići</option>
|
||||||
|
<option value="1906">Žepa</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="height:40px;">
|
||||||
|
|
||||||
|
<span class="drop-container" style="width: 168px;">
|
||||||
|
<span class="drop-label">Mjesto</span><span class="drop-arrow"></span>
|
||||||
|
<select name="" id="trebinjskofocanska" class="drop-select" onchange="stavi_grad()">
|
||||||
|
<option value="0">Mjesto</option>
|
||||||
|
<option value="4441">Berkovići</option>
|
||||||
|
<option value="183">Bileća</option>
|
||||||
|
<option value="1287">Foča</option>
|
||||||
|
<option value="1462">Gacko</option>
|
||||||
|
<option value="3038">Istočni Mostar</option>
|
||||||
|
<option value="2164">Kalinovik</option>
|
||||||
|
<option value="2884">Ljubinje</option>
|
||||||
|
<option value="3138">Nevesinje</option>
|
||||||
|
<option value="4766">Trebinje</option>
|
||||||
|
<option value="911">Čajniče</option>
|
||||||
|
</select>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
const stavi_grad = () => {};
|
||||||
|
const gradovi = [
|
||||||
|
{"ime":" Sarajevo","id":"sarajevo"},
|
||||||
|
{"ime":" Unsko-sanski","id":"unskosanski"},
|
||||||
|
{"ime":" Posavski","id":"posavski"},
|
||||||
|
{"ime":" Tuzlanski","id":"tuzlanski"},
|
||||||
|
{"ime":" Zeničko-dobojski","id":"zenickodobojski"},
|
||||||
|
{"ime":" Bosansko-podrinjski","id":"bosanskopodrinjski"},
|
||||||
|
{"ime":" Srednjobosanski","id":"srednjobosanski"},
|
||||||
|
{"ime":" Hercegovačko-neretvanski","id":"hercegovackoneretvanski"},
|
||||||
|
{"ime":" Zapadno-hercegovački","id":"zapadnohercegovacki"},
|
||||||
|
{"ime":" Livanjski","id":"livanjski"},
|
||||||
|
{"ime":" Banjalučka","id":"banjalučka"},
|
||||||
|
{"ime":" Dobojsko-Bijeljinska","id":"dobojskobijeljinska"},
|
||||||
|
{"ime":" Sarajevsko-Zvornička","id":"sarajevskozvornicka"},
|
||||||
|
{"ime":" Trebinjsko-Fočanska","id":"trebinjskofocanska"},
|
||||||
|
{"ime":"Distrikt Brčko","id":"distriktbrcko"},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let grad of gradovi) {
|
||||||
|
const mjesta = [];
|
||||||
|
$('#' + grad.id).children().each( function() {
|
||||||
|
const mjesto = $(this).text();
|
||||||
|
mjesta.push( {
|
||||||
|
ime: mjesto,
|
||||||
|
id: mjesto.toLowerCase().replace(/[^a-z]/g,''),
|
||||||
|
olxid: $(this).val()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
grad.mjesta = mjesta;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(JSON.stringify(gradovi));
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
Reference in New Issue
Block a user