Implement renting option frontend #65

Merged
bilal.catic merged 8 commits from implement-renting-option-frontend into master 2019-10-31 19:12:43 +01:00
12 changed files with 157 additions and 61 deletions

View File

@@ -1,4 +1,4 @@
const PRICE_SLIDER_OPTIONS = { const PRICE_SLIDER_OPTIONS_SALE = {
start: [50000, 85000], start: [50000, 85000],
range: { range: {
min: [0], min: [0],
@@ -8,6 +8,16 @@ const PRICE_SLIDER_OPTIONS = {
connect: true connect: true
}; };
const PRICE_SLIDER_OPTIONS_RENT = {
start: [300, 500],
range: {
min: [0],
max: [2000]
},
step: 50,
connect: true
};
//This will be used for Flats, Apartments, Houses //This will be used for Flats, Apartments, Houses
const HOME_SIZE_SLIDER_OPTIONS = { const HOME_SIZE_SLIDER_OPTIONS = {
start: [30, 75], start: [30, 75],
@@ -59,9 +69,21 @@ const GARAGE_PRICE_SLIDER_OPTIONS = {
}; };
const AD_TYPE = { const AD_TYPE = {
AD_TYPE_SALE: "SALE", AD_TYPE_SALE: {
AD_TYPE_RENT: "RENT", id: 1,
AD_TYPE_REQUEST: "REQUEST" stringId: "SALE",
title: "Prodaja"
},
AD_TYPE_RENT: {
id: 2,
stringId: "RENT",
title: "Najam"
},
AD_TYPE_REQUEST: {
id: 3,
stringId: "REQUEST",
title: "Potražnja"
}
}; };
const AD_CATEGORY = { const AD_CATEGORY = {
@@ -72,14 +94,16 @@ const AD_CATEGORY = {
id: "FLAT", id: "FLAT",
title: "Stan", title: "Stan",
hasGardenSize: false, hasGardenSize: false,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS
}, },
HOUSE: { HOUSE: {
id: "HOUSE", id: "HOUSE",
title: "Kuća", title: "Kuća",
hasGardenSize: true, hasGardenSize: true,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS,
gardenSizeSliderOptions: GARDEN_SIZE_SLIDER_OPTIONS gardenSizeSliderOptions: GARDEN_SIZE_SLIDER_OPTIONS
}, },
@@ -87,35 +111,40 @@ const AD_CATEGORY = {
id: "OFFICE", id: "OFFICE",
title: "Kancelarija", title: "Kancelarija",
hasGardenSize: false, hasGardenSize: false,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS
}, },
LAND: { LAND: {
id: "LAND", id: "LAND",
title: "Zemljište", title: "Zemljište",
hasGardenSize: false, hasGardenSize: false,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: LAND_SIZE_SLIDER_OPTIONS sizeSliderOptions: LAND_SIZE_SLIDER_OPTIONS
}, },
APARTMENT: { APARTMENT: {
id: "APARTMENT", id: "APARTMENT",
title: "Apartman", title: "Apartman",
hasGardenSize: false, hasGardenSize: false,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS
}, },
GARAGE: { GARAGE: {
id: "GARAGE", id: "GARAGE",
title: "Garaža", title: "Garaža",
hasGardenSize: false, hasGardenSize: false,
priceSliderOptions: GARAGE_PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: GARAGE_SIZE_SLIDER_OPTIONS sizeSliderOptions: GARAGE_SIZE_SLIDER_OPTIONS
}, },
COTTAGE: { COTTAGE: {
id: "COTTAGE", id: "COTTAGE",
title: "Vikendica", title: "Vikendica",
hasGardenSize: true, hasGardenSize: true,
priceSliderOptions: PRICE_SLIDER_OPTIONS, priceSliderOptionsSale: PRICE_SLIDER_OPTIONS_SALE,
priceSliderOptionsRent: PRICE_SLIDER_OPTIONS_RENT,
sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS, sizeSliderOptions: HOME_SIZE_SLIDER_OPTIONS,
gardenSizeSliderOptions: GARDEN_SIZE_SLIDER_OPTIONS gardenSizeSliderOptions: GARDEN_SIZE_SLIDER_OPTIONS
} }

View File

@@ -3,11 +3,12 @@ const { isValidEmail } = require("../helpers/email");
const { const {
notifyForNewSearchRequest notifyForNewSearchRequest
} = require("../services/notificationService"); } = require("../services/notificationService");
const { AD_CATEGORY } = require("../common/enums"); const { AD_CATEGORY, AD_TYPE } = require("../common/enums");
const getQueryReviewData = searchRequest => { const getQueryReviewData = searchRequest => {
const { const {
id, id,
adType,
realEstateType, realEstateType,
sizeMin, sizeMin,
sizeMax, sizeMax,
@@ -22,8 +23,21 @@ const getQueryReviewData = searchRequest => {
? realEstateTypeObject.hasGardenSize ? realEstateTypeObject.hasGardenSize
: false; : false;
let adTypeTitle = "";
switch (adType) {
case AD_TYPE.AD_TYPE_SALE.stringId:
adTypeTitle = AD_TYPE.AD_TYPE_SALE.title;
break;
case AD_TYPE.AD_TYPE_RENT.stringId:
adTypeTitle = AD_TYPE.AD_TYPE_RENT.title;
break;
default:
adTypeTitle = "-";
break;
}
const realEstateTypeTitle = realEstateTypeObject const realEstateTypeTitle = realEstateTypeObject
? realEstateTypeObject.title ? `[${adTypeTitle}] ${realEstateTypeObject.title}`
: "-"; : "-";
const locationTitle = "Promjenite lokaciju"; const locationTitle = "Promjenite lokaciju";

View File

@@ -1,5 +1,5 @@
const { currentSearchRequest } = require("../helpers/url"); const { currentSearchRequest } = require("../helpers/url");
const { AD_CATEGORY } = require("../common/enums"); const { AD_CATEGORY, AD_TYPE } = require("../common/enums");
const getFilters = async (req, res) => { const getFilters = async (req, res) => {
const searchRequest = await currentSearchRequest(req); const searchRequest = await currentSearchRequest(req);
@@ -12,6 +12,7 @@ const getFilters = async (req, res) => {
const title = "Filteri za pretraživanje"; const title = "Filteri za pretraživanje";
const { const {
adType,
realEstateType, realEstateType,
priceMin, priceMin,
priceMax, priceMax,
@@ -24,11 +25,22 @@ const getFilters = async (req, res) => {
const { const {
hasGardenSize, hasGardenSize,
priceSliderOptions, priceSliderOptionsSale,
priceSliderOptionsRent,
sizeSliderOptions, sizeSliderOptions,
gardenSizeSliderOptions gardenSizeSliderOptions
} = category; } = category;
let priceSliderOptions;
if (adType === AD_TYPE.AD_TYPE_SALE.stringId) {
priceSliderOptions = Object.assign({}, priceSliderOptionsSale);
} else if (adType === AD_TYPE.AD_TYPE_RENT.stringId) {
priceSliderOptions = Object.assign({}, priceSliderOptionsRent);
} else {
res.render("notFound", { title: " " });
return;
}
if (priceMin || priceMax) { if (priceMin || priceMax) {
priceSliderOptions.start = [priceMin, priceMax]; priceSliderOptions.start = [priceMin, priceMax];
} }

View File

@@ -1,20 +1,45 @@
const { currentSearchRequest } = require("../helpers/url"); const { currentSearchRequest } = require("../helpers/url");
const { createSearchRequest } = require("../helpers/db/searchRequest"); const { createSearchRequest } = require("../helpers/db/searchRequest");
const { AD_CATEGORY } = require("../common/enums"); const { AD_CATEGORY, AD_TYPE } = require("../common/enums");
const getRealEstateTypes = async (req, res) => {
const searchRequest = await currentSearchRequest(req);
const getRealEstateTypes = (req, res) => {
const title = "Koju nekretninu tražite?"; const title = "Koju nekretninu tražite?";
let selectedAdType = AD_TYPE.AD_TYPE_SALE.id;
if (
searchRequest &&
searchRequest.adType &&
searchRequest.adType === AD_TYPE.AD_TYPE_RENT.stringId
) {
selectedAdType = AD_TYPE.AD_TYPE_RENT.id;
}
const realEstateTypes = Object.keys(AD_CATEGORY) const realEstateTypes = Object.keys(AD_CATEGORY)
.map(category => AD_CATEGORY[category]) .map(category => AD_CATEGORY[category])
.filter(category => category.title); .filter(category => category.title);
res.render("realEstateType", { realEstateTypes, title }); res.render("realEstateType", {
selectedAdType,
realEstateTypes,
title,
AD_TYPE
});
}; };
const postRealEstateTypes = async (req, res) => { const postRealEstateTypes = async (req, res) => {
const searchRequest = await currentSearchRequest(req); const searchRequest = await currentSearchRequest(req);
const adType = parseInt(req.body.adType);
const adTypeStringIds = {
[AD_TYPE.AD_TYPE_SALE.id]: AD_TYPE.AD_TYPE_SALE.stringId,
[AD_TYPE.AD_TYPE_RENT.id]: AD_TYPE.AD_TYPE_RENT.stringId
};
const adTypeStringId =
adTypeStringIds[adType] || AD_TYPE.AD_TYPE_SALE.stringId;
const validRealEstateTypes = Object.keys(AD_CATEGORY).filter( const validRealEstateTypes = Object.keys(AD_CATEGORY).filter(
category => !!AD_CATEGORY[category].title category => !!AD_CATEGORY[category].title
); );
@@ -30,12 +55,14 @@ const postRealEstateTypes = async (req, res) => {
let nextStepUrl = ""; let nextStepUrl = "";
if (searchRequest && searchRequest.id) { if (searchRequest && searchRequest.id) {
nextStepUrl = `/${nextStepPage}/${searchRequest.id}`; nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
searchRequest.adType = adTypeStringId;
searchRequest.realEstateType = selectedRealEstateType; searchRequest.realEstateType = selectedRealEstateType;
await searchRequest.save(); await searchRequest.save();
} else { } else {
try { try {
const newSearchRequest = await createSearchRequest({ const newSearchRequest = await createSearchRequest({
adType: adTypeStringId,
realEstateType: selectedRealEstateType realEstateType: selectedRealEstateType
}); });

View File

@@ -342,9 +342,9 @@ class AktidoCrawler {
getKiviAdTypeFromAktidoActionId(actionId) { getKiviAdTypeFromAktidoActionId(actionId) {
switch (actionId) { switch (actionId) {
case 1: case 1:
return AD_TYPE.AD_TYPE_SALE; return AD_TYPE.AD_TYPE_SALE.stringId;
case 2: case 2:
return AD_TYPE.AD_TYPE_RENT; return AD_TYPE.AD_TYPE_RENT.stringId;
default: default:
return undefined; return undefined;
} }

View File

@@ -475,11 +475,11 @@ class OlxCrawler {
getAdTypeId(adTypeText) { getAdTypeId(adTypeText) {
switch (adTypeText) { switch (adTypeText) {
case "Prodaja": case "Prodaja":
return AD_TYPE.AD_TYPE_SALE; return AD_TYPE.AD_TYPE_SALE.stringId;
case "Izdavanje": case "Izdavanje":
return AD_TYPE.AD_TYPE_RENT; return AD_TYPE.AD_TYPE_RENT.stringId;
case "Potražnja": case "Potražnja":
return AD_TYPE.AD_TYPE_RENT; return AD_TYPE.AD_TYPE_RENT.stringId;
default: default:
return undefined; return undefined;
} }

View File

@@ -228,9 +228,9 @@ class ProstorCrawler {
static getAdTypeId(adTypeText) { static getAdTypeId(adTypeText) {
switch (adTypeText) { switch (adTypeText) {
case "prodaja": case "prodaja":
return AD_TYPE.AD_TYPE_SALE; return AD_TYPE.AD_TYPE_SALE.stringId;
case "najam": case "najam":
return AD_TYPE.AD_TYPE_RENT; return AD_TYPE.AD_TYPE_RENT.stringId;
default: default:
return undefined; return undefined;
} }

View File

@@ -342,9 +342,9 @@ class RentalCrawler {
getKiviAdTypeFromRentalActionId(actionId) { getKiviAdTypeFromRentalActionId(actionId) {
switch (actionId) { switch (actionId) {
case 1: case 1:
return AD_TYPE.AD_TYPE_SALE; return AD_TYPE.AD_TYPE_SALE.stringId;
case 2: case 2:
return AD_TYPE.AD_TYPE_RENT; return AD_TYPE.AD_TYPE_RENT.stringId;
default: default:
return undefined; return undefined;
} }

View File

@@ -26,7 +26,7 @@ module.exports = (sequelize, DataTypes) => {
adType: { adType: {
type: DataTypes.TEXT, type: DataTypes.TEXT,
allowNull: false, allowNull: false,
defaultValue: AD_TYPE.AD_TYPE_SALE defaultValue: AD_TYPE.AD_TYPE_SALE.stringId
}, },
email: DataTypes.TEXT, email: DataTypes.TEXT,
locality: DataTypes.TEXT, locality: DataTypes.TEXT,

View File

@@ -1,32 +1,29 @@
.ui-segment{ .ui-segment {
color: #02adba; color: #02adba;
border: 1px solid #02adba; border: 1px solid #02adba;
border-radius: 4px; border-radius: 4px;
display:inline-block; display: inline-block;
} }
.ui-segment span.option.active{ .ui-segment span.option.active {
background-color: #02adba; background-color: #02adba;
color: white; color: white;
} }
.ui-segment span.option{ .ui-segment span.option {
padding-left: 30px; padding-left: 30px;
padding-right: 30px; padding-right: 30px;
height: 35px; height: 35px;
text-align:center; text-align: center;
display:inline-block; display: inline-block;
line-height: 35px; line-height: 35px;
margin: 0px; margin: 0px;
float:left; float: left;
cursor:pointer; cursor: pointer;
border-right:1px solid #02adba; border-right: 1px solid #02adba;
}
.ui-segment span.option[disabled]{
color: gray;
} }
.ui-segment span.option:last-child{ .ui-segment span.option:last-child {
border-right: none; border-right: none;
} }
.segment-select{ .segment-select {
display:none; display: none;
} }

View File

@@ -58,6 +58,7 @@
} }
if (simpleEmailRegex.test(email)){ if (simpleEmailRegex.test(email)){
$("#submit").attr("disabled", true);
$("#form-queryreview").submit(); $("#form-queryreview").submit();
}else{ }else{
$("#error-label-email").text("Greška ! Unešeni emailovi nisu isti"); $("#error-label-email").text("Greška ! Unešeni emailovi nisu isti");

View File

@@ -3,14 +3,22 @@
<div class="center-align"> <div class="center-align">
<div class="row"> <div class="row">
<select class="segment-select"> <select class="segment-select" id="adType" name="adType">
<option value="1">Prodaja</option> <option value="<%= AD_TYPE.AD_TYPE_SALE.id %>"
<option value="2" disabled>Najam (uskoro)</option> <% if (selectedAdType === AD_TYPE.AD_TYPE_SALE.id) { %>
selected="selected"
<% } %>
><%= AD_TYPE.AD_TYPE_SALE.title %></option>
<option value="<%= AD_TYPE.AD_TYPE_RENT.id %>"
<% if (selectedAdType === AD_TYPE.AD_TYPE_RENT.id) { %>
selected="selected"
<% } %>
><%= AD_TYPE.AD_TYPE_RENT.title %></option>
</select> </select>
</div> </div>
<br> <br>
<div class="collection"> <div id="realEstateTypeSelection" class="collection">
<% for(const realEstateType of realEstateTypes) { %> <% for(const realEstateType of realEstateTypes) { %>
<a class="waves-effect row collection-item" <a class="waves-effect row collection-item"
@@ -33,16 +41,17 @@
$.fn.extend({ $.fn.extend({
Segment: function() { Segment: function() {
$(this).each(function() { $(this).each(function() {
const self = $(this);
const onchange = self.attr('onchange');
const wrapper = $("<div>", { class: "ui-segment" }); const wrapper = $("<div>", { class: "ui-segment" });
$(this) $(this)
.find("option") .find("option")
.each(function(param, param2) { .each(function() {
const isDisabled = $(param2).attr("disabled");
const option = $("<span>", { const option = $("<span>", {
class: "option", class: "option",
onclick: onchange,
text: $(this).text(), text: $(this).text(),
value: $(this).val(), value: $(this).val(),
disabled: isDisabled
}); });
if ($(this).is(":selected")) { if ($(this).is(":selected")) {
option.addClass("active"); option.addClass("active");
@@ -50,6 +59,12 @@
wrapper.append(option); wrapper.append(option);
}); });
wrapper.find("span.option").click(function (){
wrapper.find("span.option").removeClass("active");
$(this).addClass("active");
self.val($(this).attr('value'));
});
$(this).after(wrapper); $(this).after(wrapper);
$(this).hide(); $(this).hide();
}); });
@@ -63,6 +78,7 @@
function saveAndSubmit(id) { function saveAndSubmit(id) {
$("#realEstateType").val(id); $("#realEstateType").val(id);
$("#realEstateTypeSelection > a").attr("onclick", "");
$("#form-real-estate-type").submit(); $("#form-real-estate-type").submit();
} }
</script> </script>