Merge branch 'simplify-location-search' into 'master'
Simplify location search See merge request saburly/marketalarm/web!27
This commit was merged in pull request #27.
This commit is contained in:
@@ -1,28 +1,42 @@
|
||||
const { currentRERequest } = require("../helpers/url");
|
||||
|
||||
const getNeighborhood = async (req, res) => {
|
||||
const getLocation = async (req, res) => {
|
||||
const title = "U kojem naselju tražite nekretninu?";
|
||||
const municipality = req.params.municipality;
|
||||
const nextStep = req.query.nextStep || "/";
|
||||
|
||||
res.render("neighborhoodMap", {
|
||||
res.render("location", {
|
||||
nextStep,
|
||||
municipality,
|
||||
title
|
||||
});
|
||||
};
|
||||
|
||||
const postNeighborhood = async (req, res) => {
|
||||
const postLocation = 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 = {
|
||||
request.locationInput =
|
||||
req.body.locationInput && req.body.locationInput.length > 0
|
||||
? req.body.locationInput
|
||||
: null;
|
||||
|
||||
request.boundingBox = {
|
||||
type: "Polygon",
|
||||
coordinates: [[northWest, northEast, southEast, southWest, northWest]]
|
||||
};
|
||||
|
||||
let locationInputData;
|
||||
if (req.body.locationInputData) {
|
||||
try {
|
||||
locationInputData = JSON.parse(req.body.locationInputData);
|
||||
} catch (e) {
|
||||
locationInputData = null;
|
||||
}
|
||||
}
|
||||
|
||||
await request.save();
|
||||
|
||||
const nextStepPage = req.query.nextStep || "povrsina";
|
||||
@@ -32,6 +46,6 @@ const postNeighborhood = async (req, res) => {
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getNeighborhood,
|
||||
postNeighborhood
|
||||
getLocation,
|
||||
postLocation
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
const { currentRERequest } = require("../helpers/url");
|
||||
const {
|
||||
getMunicipalitiesForRegion,
|
||||
getMunicipalityName
|
||||
} = require("../helpers/codes");
|
||||
|
||||
const getMunicipality = async (req, res) => {
|
||||
const title = "U kojem mjestu tražite nekretninu?";
|
||||
let request = await currentRERequest(req);
|
||||
const municipalities = getMunicipalitiesForRegion(request.region);
|
||||
|
||||
res.render("municipality", { municipalities, title });
|
||||
};
|
||||
|
||||
const postMunicipality = async (req, res) => {
|
||||
const request = await currentRERequest(req);
|
||||
const nextStepParam = req.query.nextStep
|
||||
? "?nextStep=" + req.query.nextStep
|
||||
: "";
|
||||
const nextStepUrl = `/${"naselje"}/${request.uniqueId}/${getMunicipalityName(
|
||||
request.region,
|
||||
req.body.municipality
|
||||
)}${nextStepParam}`;
|
||||
|
||||
request.municipality = req.body.municipality;
|
||||
await request.save();
|
||||
|
||||
res.redirect(nextStepUrl);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getMunicipality,
|
||||
postMunicipality
|
||||
};
|
||||
@@ -1,10 +1,6 @@
|
||||
const { currentRERequest } = require("../helpers/url");
|
||||
const { getRegionName, getMunicipalityName } = require("../helpers/codes");
|
||||
const {
|
||||
realEstateTypes,
|
||||
sizes,
|
||||
gardenSizes,
|
||||
prices,
|
||||
getEnumTypeTitle,
|
||||
getRealEstateTypeEnum
|
||||
} = require("../helpers/enums");
|
||||
@@ -20,14 +16,13 @@ const getQueryReview = async (req, res) => {
|
||||
|
||||
const {
|
||||
realEstateType,
|
||||
region,
|
||||
municipality,
|
||||
sizeMin,
|
||||
sizeMax,
|
||||
gardenSizeMin,
|
||||
gardenSizeMax,
|
||||
priceMin,
|
||||
priceMax
|
||||
priceMax,
|
||||
locationInput
|
||||
} = request.dataValues;
|
||||
|
||||
const realEstateTypeObject = getRealEstateTypeEnum(realEstateType);
|
||||
@@ -38,9 +33,9 @@ const getQueryReview = async (req, res) => {
|
||||
const realEstateTypeTitle = realEstateType
|
||||
? getEnumTypeTitle(realEstateTypes, realEstateType)
|
||||
: null;
|
||||
const regionName = region ? getRegionName(region) : null;
|
||||
const municipalityName =
|
||||
region && municipality ? getMunicipalityName(region, municipality) : null;
|
||||
|
||||
const locationTitle = locationInput ? locationInput : "-";
|
||||
|
||||
const sizeTitle = sizeMin ? sizeMin + "-" + sizeMax + " m2" : null;
|
||||
const gardenSizeTitle = gardenSizeMin
|
||||
? gardenSizeMin + "-" + gardenSizeMax + " m2"
|
||||
@@ -58,14 +53,9 @@ const getQueryReview = async (req, res) => {
|
||||
url: `/vrstanekretnine/${uniqueId}?nextStep=pregled`
|
||||
},
|
||||
{
|
||||
id: "region",
|
||||
title: regionName,
|
||||
url: `/grad/${uniqueId}?nextStep=mjesto`
|
||||
},
|
||||
{
|
||||
id: "municipality",
|
||||
title: municipalityName,
|
||||
url: `/mjesto/${uniqueId}?nextStep=pregled`
|
||||
id: "location",
|
||||
title: locationTitle,
|
||||
url: `/lokacija/${uniqueId}?nextStep=pregled`
|
||||
},
|
||||
{
|
||||
id: "size",
|
||||
|
||||
@@ -11,7 +11,7 @@ const getRealEstateTypes = (req, res) => {
|
||||
const postRealEstateTypes = async (req, res) => {
|
||||
const request = await currentRERequest(req);
|
||||
|
||||
const nextStepPage = req.query.nextStep || "grad";
|
||||
const nextStepPage = req.query.nextStep || "lokacija";
|
||||
|
||||
if (request && request.uniqueId) {
|
||||
const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
const { currentRERequest } = require("../helpers/url");
|
||||
const { getRegions } = require("../helpers/codes");
|
||||
|
||||
const regions = getRegions();
|
||||
|
||||
const getRegion = (req, res) => {
|
||||
const title = "U kojoj regiji tražite nekretninu?";
|
||||
res.render("region", { regions, title });
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
@@ -2,7 +2,7 @@ const { APP_URL } = require("../config/appConfig");
|
||||
const { getRealEstateTypeEnum } = require("./enums");
|
||||
const { getRegionName, getMunicipalityName } = require("./codes");
|
||||
const { allRERequestByUiid } = require("./db/dbHelper");
|
||||
var AWS = require("aws-sdk");
|
||||
let AWS = require("aws-sdk");
|
||||
const TEMPLATE_NAME = "MarketAlertTemplate";
|
||||
|
||||
AWS.config.update({
|
||||
@@ -30,16 +30,12 @@ const sendTemplatedEmail = async (email, request) => {
|
||||
},
|
||||
Text: {
|
||||
Charset: "UTF-8",
|
||||
Data: getGreetingsEmaiTextVersion(request)
|
||||
Data: getGreetingsEmailTextVersion(request)
|
||||
}
|
||||
},
|
||||
Subject: {
|
||||
Charset: "UTF-8",
|
||||
Data: `Javimi Potvrda: ${getSubject(
|
||||
request.realEstateType,
|
||||
request.region,
|
||||
request.municipality
|
||||
)}`
|
||||
Data: `Javimi Potvrda: ${getSubject(request.realEstateType)}`
|
||||
}
|
||||
},
|
||||
Source: process.env.SOURCE_EMAIL /* required */,
|
||||
@@ -52,12 +48,12 @@ const sendTemplatedEmail = async (email, request) => {
|
||||
await sendEmailPromise;
|
||||
};
|
||||
|
||||
const getGreetingsEmailHTML = realestateRequest => {
|
||||
const getGreetingsEmailHTML = realEstateRequest => {
|
||||
const realEstateType = getRealEstateTypeEnum(
|
||||
realestateRequest.realEstateType
|
||||
realEstateRequest.realEstateType
|
||||
);
|
||||
const gardenSize = realEstateType.hasGardenSize
|
||||
? `<div><strong>Kvadratura okućnice: Od ${realestateRequest.gardenSizeMin} do ${realestateRequest.gardenSizeMax} m2 </strong></div>`
|
||||
? `<div><strong>Kvadratura okućnice: Od ${realEstateRequest.gardenSizeMin} do ${realEstateRequest.gardenSizeMax} m2 </strong></div>`
|
||||
: ``;
|
||||
|
||||
return `<h1> Zdravo,
|
||||
@@ -65,63 +61,40 @@ const getGreetingsEmailHTML = realestateRequest => {
|
||||
<h2> Ovo je tražena nekretnina: </h2>
|
||||
<div>
|
||||
<div> <strong>Tip nekretnine: ${realEstateType.title} </strong></div>
|
||||
<div><strong>Područje: ${getRegionName(
|
||||
realestateRequest.region
|
||||
)} </strong></div>
|
||||
<div><strong>Mjesto: ${getMunicipalityName(
|
||||
realestateRequest.region,
|
||||
realestateRequest.municipality
|
||||
)} </strong></div>
|
||||
<div><strong>Kvadratura nekretnine: Od ${realestateRequest.sizeMin} do ${
|
||||
realestateRequest.sizeMax
|
||||
} m2 </strong></div>
|
||||
<div><strong>Lokacija: </strong></div>
|
||||
<div><strong>Kvadratura nekretnine: Od ${realEstateRequest.sizeMin} do ${realEstateRequest.sizeMax} m2 </strong></div>
|
||||
${gardenSize}
|
||||
<div><strong>Cijena: ${realestateRequest.priceMin} do ${
|
||||
realestateRequest.priceMax
|
||||
} KM </strong></div>
|
||||
<div><strong>Cijena: ${realEstateRequest.priceMin} do ${realEstateRequest.priceMax} KM </strong></div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<div><strong> Ako želis prestati dobijati obavještenja za ovu pretragu klikni ${APP_URL}/odjava/${
|
||||
realestateRequest.uniqueId
|
||||
} </strong></div>
|
||||
<div><strong>Ako želiš promijeniti uslove pretrage klikni ${APP_URL}/pregled/${
|
||||
realestateRequest.uniqueId
|
||||
} </strong></div>
|
||||
<div><strong> Ako želis prestati dobijati obavještenja za ovu pretragu klikni ${APP_URL}/odjava/${realEstateRequest.uniqueId} </strong></div>
|
||||
<div><strong>Ako želiš promijeniti uslove pretrage klikni ${APP_URL}/pregled/${realEstateRequest.uniqueId} </strong></div>
|
||||
<h4> Tvoj,
|
||||
Javimi tim.
|
||||
</h4>`;
|
||||
};
|
||||
|
||||
const getGreetingsEmaiTextVersion = realestateRequest => {
|
||||
const getGreetingsEmailTextVersion = realEstateRequest => {
|
||||
const realEstateType = getRealEstateTypeEnum(
|
||||
realestateRequest.realEstateType
|
||||
realEstateRequest.realEstateType
|
||||
);
|
||||
const gardenSize = realEstateType.hasGardenSize
|
||||
? `Kvadratura okućnice od ${realestateRequest.gardenSizeMin} do ${realestateRequest.gardenSizeMax}`
|
||||
? `Kvadratura okućnice od ${realEstateRequest.gardenSizeMin} do ${realEstateRequest.gardenSizeMax}`
|
||||
: "";
|
||||
|
||||
const text = `Zdravo, \n Naručio/la si da ti javimo ako se nekretnina pojavi u oglasima
|
||||
\n Ovo je tražena nekretnina: \n , Tip nekretnine: ${
|
||||
realestateRequest.realEstateType
|
||||
} \n Područje ${getRegionName(
|
||||
realestateRequest.region
|
||||
)} \n Mjesto ${getMunicipalityName(
|
||||
realestateRequest.region,
|
||||
realestateRequest.municipality
|
||||
)}
|
||||
\n Kvadratura nekretnine Od ${realestateRequest.sizeMin} do ${
|
||||
realestateRequest.sizeMaX
|
||||
} ${gardenSize} \n Cijena od ${realestateRequest.priceMin} do ${
|
||||
realestateRequest.priceMax
|
||||
} \n Ako želis prestati dobijati obavještenja za ovu pretragu klikni
|
||||
${APP_URL}/odjava/${
|
||||
realestateRequest.uniqueId
|
||||
}\n Ako želiš promijeniti uslove pretrage klikni
|
||||
${APP_URL}/odpregled/${realestateRequest.uniqueId}\n Tvoj,\n Javimi tim`;
|
||||
|
||||
return text;
|
||||
return `Zdravo\nNaručio/la si da ti javimo ako se nekretnina pojavi u oglasima\n
|
||||
Ovo je tražena nekretnina:\nTip nekretnine: ${realEstateRequest.realEstateType}\n
|
||||
Lokacija nekretnine :\n
|
||||
Kvadratura nekretnine Od ${realEstateRequest.sizeMin} do ${realEstateRequest.sizeMax}
|
||||
${gardenSize}\n
|
||||
Cijena od ${realEstateRequest.priceMin} do ${realEstateRequest.priceMax} \n
|
||||
Ako želis prestati dobijati obavještenja za ovu pretragu klikni
|
||||
${APP_URL}/odjava/${realEstateRequest.uniqueId}\n
|
||||
Ako želiš promijeniti uslove pretrage klikni
|
||||
${APP_URL}/odpregled/${realEstateRequest.uniqueId}\n
|
||||
Tvoj,\n Javimi tim`;
|
||||
};
|
||||
|
||||
const sendBulkEmail = async marketAlerts => {
|
||||
@@ -249,8 +222,7 @@ const createMarketAlertEmailTemplate = async () => {
|
||||
const marketAlertTemplate = {
|
||||
Template: {
|
||||
TemplateName: TEMPLATE_NAME,
|
||||
SubjectPart:
|
||||
"Javi mi obavijest: {{realestateType}}, {{region}}, {{municipality}}",
|
||||
SubjectPart: "Javi mi obavijest: {{realestateType}}",
|
||||
TextPart: getNotificationEmailText(),
|
||||
HtmlPart: getNotificationEmailHtml()
|
||||
}
|
||||
@@ -266,10 +238,8 @@ const createMarketAlertEmailTemplate = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const getSubject = (realEstateType, region, municipality) => {
|
||||
return `${getRealEstateTypeEnum(realEstateType).title} ${getRegionName(
|
||||
region
|
||||
)}, ${getMunicipalityName(region, municipality)}`;
|
||||
const getSubject = realEstateType => {
|
||||
return getRealEstateTypeEnum(realEstateType).title;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -27,8 +27,8 @@ module.exports = class OlxCrawler {
|
||||
|
||||
async crawl() {
|
||||
const filteredResults = [];
|
||||
const realestateRequests = await allRERequest();
|
||||
const urls = this.createRequestUrls(realestateRequests);
|
||||
const realEstateRequests = await allRERequest();
|
||||
const urls = this.createRequestUrls(realEstateRequests);
|
||||
let results = await this.indexPages(
|
||||
urls,
|
||||
this.fromPage,
|
||||
@@ -65,24 +65,94 @@ module.exports = class OlxCrawler {
|
||||
return [];
|
||||
}
|
||||
|
||||
createRequestUrls(realestateRequests) {
|
||||
createRequestUrls(realEstateRequests) {
|
||||
const urls = [];
|
||||
|
||||
for (const request of realestateRequests) {
|
||||
const realsestateType =
|
||||
"kategorija=" +
|
||||
getRealEstateTypeEnum(request.realEstateType).olxCategory;
|
||||
const region = "kanton=" + getRegion(request.region).olxid;
|
||||
const municipality =
|
||||
"grad%5B%5D=" +
|
||||
getMunicipality(request.region, request.municipality).olxid;
|
||||
const sizeMin = "kvadrata_min=" + request.sizeMin;
|
||||
const sizeMax = "kvadrata_max=" + request.sizeMax;
|
||||
const priceMin = "od=" + request.priceMin;
|
||||
const priceMax = "do=" + request.priceMax;
|
||||
for (const request of realEstateRequests) {
|
||||
const {
|
||||
realEstateType,
|
||||
region,
|
||||
sizeMin,
|
||||
sizeMax,
|
||||
priceMin,
|
||||
priceMax
|
||||
} = request;
|
||||
|
||||
const urlRealEstateParams = [
|
||||
{
|
||||
paramName: "kanton",
|
||||
paramValue: region,
|
||||
useParam: false
|
||||
},
|
||||
{
|
||||
paramName: "kategorija",
|
||||
paramValue: getRealEstateTypeEnum(realEstateType).olxid,
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "kvadrata_min",
|
||||
paramValue: sizeMin,
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "kvadrata_max",
|
||||
paramValue: sizeMax,
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "od",
|
||||
paramValue: priceMin,
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "do",
|
||||
paramValue: priceMax,
|
||||
useParam: true
|
||||
}
|
||||
];
|
||||
const urlResultsParams = [
|
||||
{
|
||||
paramName: "vrstapregleda",
|
||||
paramValue: "tabela",
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "sort_order",
|
||||
paramValue: "desc",
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "vrsta",
|
||||
paramValue: "samoprodaja",
|
||||
useParam: true
|
||||
},
|
||||
{
|
||||
paramName: "stranica",
|
||||
paramValue: "0",
|
||||
useParam: true
|
||||
}
|
||||
];
|
||||
|
||||
const paramsReduceFunction = (accumulatedValue, currentParam) => {
|
||||
const { paramName, paramValue, useParam } = currentParam;
|
||||
if (useParam) {
|
||||
return `${accumulatedValue}&${paramName}=${paramValue}`;
|
||||
} else {
|
||||
return accumulatedValue;
|
||||
}
|
||||
};
|
||||
|
||||
const reducedRealEstateParams = urlRealEstateParams.reduce(
|
||||
paramsReduceFunction,
|
||||
""
|
||||
);
|
||||
const reducedResultsParams = urlResultsParams.reduce(
|
||||
paramsReduceFunction,
|
||||
""
|
||||
);
|
||||
|
||||
const olxUrl = {
|
||||
url: `https://www.olx.ba/pretraga?${realsestateType}&id=2&stanje=0&vrstapregleda=tabela&sort_order=desc&${region}&${municipality}&${priceMin}&${priceMax}&vrsta=samoprodaja&${sizeMin}&${sizeMax}&stranica=`,
|
||||
url: `https://www.olx.ba/pretraga?${reducedRealEstateParams}${reducedResultsParams}`,
|
||||
email: request.email,
|
||||
uuid: request.uniqueId,
|
||||
hrefs: this.hrefs
|
||||
@@ -313,9 +383,10 @@ class Indexer {
|
||||
|
||||
const parsedPrice = parsePrice(price);
|
||||
|
||||
const locationArray = location.split(",");
|
||||
const region = locationArray[0];
|
||||
const municipality = locationArray[1];
|
||||
const locationArray =
|
||||
location && location.length > 0 ? location.split(",") : [];
|
||||
const region = locationArray.length > 0 ? locationArray[0] : "";
|
||||
const municipality = locationArray.length > 1 ? locationArray[1] : "";
|
||||
|
||||
const data = {
|
||||
realEstateType: this.getCategoryId(realEstateType),
|
||||
|
||||
@@ -90,7 +90,7 @@ const getMarketAlertById = async id => {
|
||||
*/
|
||||
const findPointInsideBoundingBox = async (latLng, email, uniqueId) => {
|
||||
return await db.sequelize.query(
|
||||
`SELECT * FROM "RealEstateRequests" WHERE email = '${email}' AND "uniqueId" = '${uniqueId}' AND subscribed = true AND ST_Contains("RealEstateRequests".bounding_box, ST_GEOMFROMTEXT('POINT (${
|
||||
`SELECT * FROM "RealEstateRequests" WHERE email = '${email}' AND "uniqueId" = '${uniqueId}' AND subscribed = true AND ST_Contains("RealEstateRequests"."boundingBox", ST_GEOMFROMTEXT('POINT (${
|
||||
latLng[0]
|
||||
} ${latLng[1]})'))`
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const realEstateTypes = [
|
||||
{ title: "Kuća", id: "kuca", hasGardenSize: true, olxCategory: 24 },
|
||||
{ title: "Stan", id: "stan", hasGardenSize: false, olxCategory: 23 },
|
||||
{ title: "Vikendica", id: "vikendica", hasGardenSize: true, olxCategory: 26 }
|
||||
{ title: "Kuća", id: "kuca", hasGardenSize: true, olxid: 24 },
|
||||
{ title: "Stan", id: "stan", hasGardenSize: false, olxid: 23 },
|
||||
{ title: "Vikendica", id: "vikendica", hasGardenSize: true, olxid: 26 }
|
||||
];
|
||||
|
||||
const sizes = [
|
||||
|
||||
@@ -4,8 +4,7 @@ const currentRERequest = async req => {
|
||||
const uniqueId = req.params["request_id"];
|
||||
if (!uniqueId) return null;
|
||||
|
||||
const request = await db.RealEstateRequest.findOne({ where: { uniqueId } });
|
||||
return request;
|
||||
return await db.RealEstateRequest.findOne({ where: { uniqueId } });
|
||||
};
|
||||
module.exports = {
|
||||
currentRERequest
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface, Sequelize) => {
|
||||
return queryInterface.addColumn("RealEstateRequests", "locationInput", {
|
||||
type: Sequelize.STRING
|
||||
});
|
||||
},
|
||||
|
||||
down: (queryInterface, Sequelize) => {
|
||||
return queryInterface.removeColumn("RealEstateRequests", "locationInput");
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface, Sequelize) => {
|
||||
return queryInterface.renameColumn(
|
||||
"RealEstateRequests",
|
||||
"bounding_box",
|
||||
"boundingBox"
|
||||
);
|
||||
},
|
||||
|
||||
down: (queryInterface, Sequelize) => {
|
||||
return queryInterface.renameColumn(
|
||||
"RealEstateRequests",
|
||||
"boundingBox",
|
||||
"bounding_box"
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -19,8 +19,9 @@ module.exports = (sequelize, DataTypes) => {
|
||||
gardenSizeMax: DataTypes.INTEGER,
|
||||
priceMin: DataTypes.INTEGER,
|
||||
priceMax: DataTypes.INTEGER,
|
||||
bounding_box: DataTypes.GEOMETRY("POINT", 4326),
|
||||
subscribed: DataTypes.BOOLEAN
|
||||
boundingBox: DataTypes.GEOMETRY("POINT", 4326),
|
||||
subscribed: DataTypes.BOOLEAN,
|
||||
locationInput: DataTypes.STRING
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
121
app/views/location.ejs
Normal file
121
app/views/location.ejs
Normal file
@@ -0,0 +1,121 @@
|
||||
<% include partials/navBar %>
|
||||
|
||||
<div class="row center-align">
|
||||
<div class="col s11">
|
||||
<input class="col s11" id="autocompleteInput" placeholder="Lokacija..." type="text" />
|
||||
</div>
|
||||
<div class="col s1">
|
||||
<a id="locateMe" class="btn-floating btn-large waves-effect waves-light"><i class="material-icons">gps_fixed</i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="map"></div>
|
||||
<br/>
|
||||
</div>
|
||||
<form method="POST" id="form-map-output">
|
||||
<div class="row center-align">
|
||||
<div class="col s6 push-s3">
|
||||
<a id="submit" 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" />
|
||||
<input type="hidden" name="locationInput" id="locationInput" />
|
||||
<input type="hidden" name="locationInputData" id="locationInputData" />
|
||||
</form>
|
||||
<script>
|
||||
let autocomplete;
|
||||
let map;
|
||||
let places;
|
||||
let geocoder;
|
||||
|
||||
function locateMe() {
|
||||
if (navigator.geolocation) {
|
||||
|
||||
const onLocationSuccess = (position) => {
|
||||
const coordinates = position && position.coords ? position.coords : null;
|
||||
if (coordinates){
|
||||
const longitude = coordinates.longitude || null;
|
||||
const latitude = coordinates.latitude || null;
|
||||
|
||||
if (longitude && latitude && map){
|
||||
map.setCenter({lat: latitude, lng: longitude});
|
||||
map.setZoom(16);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
navigator.geolocation.getCurrentPosition(onLocationSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
function initMap() {
|
||||
const BOSNIA_BOUNDS = {
|
||||
north: 45.70,
|
||||
south: 41.69,
|
||||
west: 15.55,
|
||||
east: 20.77,
|
||||
};
|
||||
const SARAJEVO_COORDINATES = {
|
||||
lat: 43.85,
|
||||
lng: 18.41,
|
||||
};
|
||||
|
||||
const mapElement = document.getElementById('map');
|
||||
const restrictMapPanningToBosniaOnly = {
|
||||
latLngBounds: BOSNIA_BOUNDS,
|
||||
strictBounds: true,
|
||||
};
|
||||
const initialMapParams = {
|
||||
center: SARAJEVO_COORDINATES,
|
||||
zoom: 12,
|
||||
restriction: restrictMapPanningToBosniaOnly,
|
||||
mapTypeControl: false,
|
||||
panControl: false,
|
||||
zoomControl: true,
|
||||
streetViewControl: false
|
||||
};
|
||||
map = new google.maps.Map(mapElement, initialMapParams);
|
||||
|
||||
const inputElement = document.getElementById('autocompleteInput');
|
||||
const restrictAutocompleteResultsToBosniaOnly = {'country': 'ba'};
|
||||
const initialAutocompleteParams = {
|
||||
types: ['geocode'],
|
||||
componentRestrictions: restrictAutocompleteResultsToBosniaOnly,
|
||||
fields: ['geometry', 'types', 'address_components']
|
||||
};
|
||||
|
||||
autocomplete = new google.maps.places.Autocomplete(inputElement, initialAutocompleteParams);
|
||||
autocomplete.bindTo('bounds', map);
|
||||
autocomplete.addListener('place_changed', onPlaceChanged);
|
||||
}
|
||||
|
||||
function onPlaceChanged() {
|
||||
const place = autocomplete.getPlace();
|
||||
if (place.geometry) {
|
||||
map.fitBounds(place.geometry.viewport);
|
||||
map.setZoom(map.getZoom() + 1);
|
||||
$("#locationInputData").val(JSON.stringify(place));
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
$("#submit").click(() => {
|
||||
const mapBounds = map.getBounds();
|
||||
|
||||
$("#north").val(mapBounds.getNorthEast().lat());
|
||||
$("#south").val(mapBounds.getSouthWest().lat());
|
||||
$("#east").val(mapBounds.getNorthEast().lng());
|
||||
$("#west").val(mapBounds.getSouthWest().lng());
|
||||
|
||||
$("#locationInput").val(document.getElementById('autocompleteInput').value);
|
||||
|
||||
$("#form-map-output").submit();
|
||||
});
|
||||
document.getElementById("locateMe").addEventListener("click", locateMe);
|
||||
});
|
||||
</script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAna8ohfV2HBMcxGk_29vqxU5Z_bDickqg&language=bs&libraries=places&callback=initMap" async
|
||||
defer></script>
|
||||
</div>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!--suppress HtmlUnknownAnchorTarget -->
|
||||
<% include partials/navBar %>
|
||||
|
||||
<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>
|
||||
@@ -1,127 +0,0 @@
|
||||
<% include partials/navBar %>
|
||||
|
||||
<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 latLngRestrictions = [];
|
||||
|
||||
var BOSNIA_BOUNDS = {
|
||||
north: 45.70,
|
||||
south: 41.69,
|
||||
west: 15.55,
|
||||
east: 20.77,
|
||||
};
|
||||
|
||||
function initMap() {
|
||||
var geocoder = new google.maps.Geocoder();
|
||||
|
||||
document.getElementById('submit').addEventListener('click', function () {
|
||||
geocodeAddress(geocoder, map, false, latLngRestrictions);
|
||||
});
|
||||
|
||||
|
||||
|
||||
defaultAddress.value = municipality;
|
||||
geocodeAddress(geocoder, map, true);
|
||||
|
||||
$(document).ready(() => {
|
||||
$("#btnsubmit").click(() => {
|
||||
var bounds = map.getBounds();
|
||||
|
||||
$("#north").val(map.getBounds().getNorthEast().lat());
|
||||
$("#south").val(map.getBounds().getSouthWest().lat());
|
||||
$("#east").val(map.getBounds().getNorthEast().lng());
|
||||
$("#west").val(map.getBounds().getSouthWest().lng());
|
||||
|
||||
$("#form-map-output").submit();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
function geocodeAddress(geocoder, resultsMap, isInit, geocoderRestrictions) {
|
||||
|
||||
|
||||
|
||||
var address = document.getElementById('address').value;
|
||||
let geocoderOptions = geocoderRestrictions
|
||||
? { 'address': address, 'bounds': geocoderRestrictions }
|
||||
: { 'address': address }
|
||||
|
||||
geocoder.geocode(geocoderOptions, function (results, status) {
|
||||
if (status === 'OK') {
|
||||
|
||||
var bounds = results[0].geometry.bounds;
|
||||
|
||||
var resultBounds = new google.maps.LatLngBounds(
|
||||
|
||||
results[0].geometry.viewport.getSouthWest(),
|
||||
results[0].geometry.viewport.getNorthEast()
|
||||
);
|
||||
|
||||
if (isInit) {
|
||||
map = new google.maps.Map(document.getElementById('map'), {
|
||||
zoom: 11,
|
||||
});
|
||||
resultsMap = map
|
||||
}
|
||||
|
||||
// map.fitBounds(resultBounds);
|
||||
resultsMap.setCenter(results[0].geometry.location);
|
||||
|
||||
if (isInit) {
|
||||
|
||||
latLngRestrictions = new google.maps.LatLngBounds(
|
||||
new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng()),
|
||||
new google.maps.LatLng(bounds.getNorthEast().lng(), bounds.getNorthEast().lng()));
|
||||
|
||||
|
||||
let latLngRestrictionsa = {
|
||||
west: bounds.getSouthWest().lng(),
|
||||
east: bounds.getNorthEast().lng(),
|
||||
north: bounds.getNorthEast().lat(),
|
||||
south: bounds.getSouthWest().lat()
|
||||
}
|
||||
map.setOptions({
|
||||
restriction: {
|
||||
latLngBounds: latLngRestrictionsa,
|
||||
strictBounds: false,
|
||||
}
|
||||
})
|
||||
} else {
|
||||
resultsMap.setZoom(17);
|
||||
}
|
||||
|
||||
} else {
|
||||
alert('Geocode was not successful for the following reason: ' + status);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAna8ohfV2HBMcxGk_29vqxU5Z_bDickqg&callback=initMap" async
|
||||
defer></script>
|
||||
</div>
|
||||
@@ -1,27 +0,0 @@
|
||||
<!--suppress HtmlUnknownAnchorTarget -->
|
||||
<% include partials/navBar %>
|
||||
|
||||
<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>
|
||||
|
||||
20
index.js
20
index.js
@@ -6,11 +6,6 @@ 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,
|
||||
@@ -26,10 +21,7 @@ const {
|
||||
postQuerySubmit
|
||||
} = require("./app/controllers/querySubmit");
|
||||
const { getGoAgain } = require("./app/controllers/goAgain");
|
||||
const {
|
||||
getNeighborhood,
|
||||
postNeighborhood
|
||||
} = require("./app/controllers/neighborhoodMap");
|
||||
const { getLocation, postLocation } = require("./app/controllers/location");
|
||||
const { getUnsubscribe } = require("./app/controllers/unsubscribe");
|
||||
const { getRealEstates } = require("./app/controllers/realEstates");
|
||||
const { redirect } = require("./app/controllers/redirect");
|
||||
@@ -147,14 +139,8 @@ 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("/lokacija/:request_id", getLocation);
|
||||
app.post("/lokacija/:request_id", postLocation);
|
||||
|
||||
app.get("/povrsina/:request_id", getSize);
|
||||
app.post("/povrsina/:request_id", postSize);
|
||||
|
||||
Reference in New Issue
Block a user