WIP - Information for locations.
Better configuration menu. Testing retrieving JSON from GitHub (uploading).
This commit is contained in:
parent
fa25e3c983
commit
9098f42a93
15
locations/Bielsa.json
Normal file
15
locations/Bielsa.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Bielsa",
|
||||
"bus": true,
|
||||
"train": false,
|
||||
"pharmacy": null,
|
||||
"smoke": true,
|
||||
"supermarkets": [
|
||||
{
|
||||
"type": "SPAR",
|
||||
"url": "https://goo.gl/maps/KGhqH8SwMJrcwPse8"
|
||||
}
|
||||
],
|
||||
"pool": false,
|
||||
"gym": true
|
||||
}
|
15
locations/Zaragoza.json
Normal file
15
locations/Zaragoza.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Zaragoza",
|
||||
"bus": true,
|
||||
"train": true,
|
||||
"pharmacy": true,
|
||||
"smoke": true,
|
||||
"supermarkets": [
|
||||
{
|
||||
"type": "DIA",
|
||||
"url": "https://goo.gl/maps/NLCXd7GdYWS2wgBMA"
|
||||
}
|
||||
],
|
||||
"pool": true,
|
||||
"gym": true
|
||||
}
|
@ -8,8 +8,9 @@ export default class Configuration {
|
||||
|
||||
constructor() {
|
||||
document.querySelector('#main-header').innerHTML += ConfigurationHTML.create();
|
||||
|
||||
this._initEvents();
|
||||
|
||||
this._initData();
|
||||
}
|
||||
|
||||
_initEvents() {
|
||||
@ -18,6 +19,23 @@ export default class Configuration {
|
||||
Information.create();
|
||||
Configuration.toggle();
|
||||
});
|
||||
|
||||
Event.change('#max-price-per-meter', (element) => {
|
||||
const pricePerMeter = element.value
|
||||
this._updateItemMeterPrices(pricePerMeter);
|
||||
});
|
||||
}
|
||||
|
||||
_initData() {
|
||||
const maxPricePerMeter = document.querySelector('#max-price-per-meter');
|
||||
this._updateItemMeterPrices(maxPricePerMeter.value);
|
||||
}
|
||||
|
||||
_updateItemMeterPrices(pricePerMeter) {
|
||||
if (!pricePerMeter) return;
|
||||
document.querySelector('#fiftyMetersPrice').textContent = pricePerMeter * 50;
|
||||
document.querySelector('#seventyFiveMetersPrice').textContent = pricePerMeter * 75;
|
||||
document.querySelector('#hundredMetersPrice').textContent = pricePerMeter * 100;
|
||||
}
|
||||
|
||||
_extractConfiguration() {
|
||||
@ -25,11 +43,21 @@ export default class Configuration {
|
||||
return {
|
||||
enabled: container.querySelector('#enabled').checked,
|
||||
percentages: container.querySelector('#percentages').checked,
|
||||
percentages_20: container.querySelector('#percentages_20').checked,
|
||||
percentages_30: container.querySelector('#percentages_30').checked,
|
||||
percentages_50: container.querySelector('#percentages_50').checked,
|
||||
garage: container.querySelector('#garage').checked,
|
||||
exterior: container.querySelector('#exterior').checked,
|
||||
lift: container.querySelector('#lift').checked,
|
||||
'max-price': container.querySelector('#max-price').value,
|
||||
'max-price-per-meter': container.querySelector('#max-price-per-meter').value
|
||||
'max-price-per-meter': container.querySelector('#max-price-per-meter').value,
|
||||
bus: container.querySelector('#bus').checked,
|
||||
train: container.querySelector('#train').checked,
|
||||
supermarket: container.querySelector('#supermarket').checked,
|
||||
smoke: container.querySelector('#smoke').checked,
|
||||
pharmacy: container.querySelector('#pharmacy').checked,
|
||||
gym: container.querySelector('#gym').checked,
|
||||
pool: container.querySelector('#pool').checked
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,50 +24,114 @@ export default class ConfigurationHTML {
|
||||
<div class='${this.CONTAINER_CLASS_NAME}'>
|
||||
<h2>Midefos Idealista</h2>
|
||||
|
||||
<h3>Configuración global:</h3>
|
||||
<label>
|
||||
${CheckboxHTML.create('enabled', Preferences.get('enabled'))}
|
||||
<span>Habilitado</span>
|
||||
</label>
|
||||
|
||||
<h3>Busqueda:</h3>
|
||||
<div class='midefos-idealista-card'>
|
||||
<h3>Configuración global</h3>
|
||||
<label>
|
||||
${CheckboxHTML.create('enabled', Preferences.get('enabled'))}
|
||||
<span>Habilitado</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('percentages', Preferences.get('percentages'))}
|
||||
<span>Porcentajes</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('garage', Preferences.get('garage'))}
|
||||
<span>Garaje</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('exterior', Preferences.get('exterior'))}
|
||||
<span>Exterior</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('lift', Preferences.get('lift'))}
|
||||
<span>Ascensor</span>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
<span>Precio máximo: </span>
|
||||
<input type='number' id='max-price' value='${Preferences.get('max-price')}' placeholder='0'>
|
||||
</label>
|
||||
<br>
|
||||
|
||||
<label>
|
||||
<span>Precio máximo por metro: </span>
|
||||
<input type='number' id='max-price-per-meter' value='${Preferences.get('max-price-per-meter')}' placeholder='0'>
|
||||
</label>
|
||||
<br>
|
||||
<div class='midefos-idealista-card'>
|
||||
<h3>Precios</h3>
|
||||
<label>
|
||||
<span>Precio máximo: </span>
|
||||
<input type='number' id='max-price' value='${Preferences.get('max-price')}' placeholder='0'>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Precio máximo por metro: </span>
|
||||
<input type='number' id='max-price-per-meter' value='${Preferences.get('max-price-per-meter')}' placeholder='0'>
|
||||
</label>
|
||||
|
||||
|
||||
<ul>
|
||||
<li><strong>50 metros: </strong><span id='fiftyMetersPrice'>150000</span></li>
|
||||
<li><strong>75 metros: </strong><span id='seventyFiveMetersPrice'>150000</span></li>
|
||||
<li><strong>100 metros: </strong><span id='hundredMetersPrice'> 150000 </span></li>
|
||||
</ul>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('percentages', Preferences.get('percentages'))}
|
||||
<span>Calcular porcentajes</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('percentages_20', Preferences.get('percentages_20'))}
|
||||
<span>20%</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('percentages_30', Preferences.get('percentages_30'))}
|
||||
<span>30%</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('percentages_50', Preferences.get('percentages_50'))}
|
||||
<span>50%</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class='midefos-idealista-card'>
|
||||
<h3>Dispone de:</h3>
|
||||
<label>
|
||||
${CheckboxHTML.create('garage', Preferences.get('garage'))}
|
||||
<span>Garaje</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('exterior', Preferences.get('exterior'))}
|
||||
<span>Exterior</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('lift', Preferences.get('lift'))}
|
||||
<span>Ascensor</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class='midefos-idealista-card'>
|
||||
<h3>Lugar dispone de:</h3>
|
||||
|
||||
<h4>Transporte público:</h4>
|
||||
<label>
|
||||
${CheckboxHTML.create('bus', Preferences.get('bus'))}
|
||||
<span>Bus</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('train', Preferences.get('train'))}
|
||||
<span>Tren</span>
|
||||
</label>
|
||||
|
||||
<h4>Comercio:</h4>
|
||||
<label>
|
||||
${CheckboxHTML.create('supermarket', Preferences.get('supermarket'))}
|
||||
<span>Supermercado</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('smoke', Preferences.get('smoke'))}
|
||||
<span>Estanco</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('pharmacy', Preferences.get('pharmacy'))}
|
||||
<span>Farmacia</span>
|
||||
</label>
|
||||
|
||||
<h4>Deporte:</h4>
|
||||
<label>
|
||||
${CheckboxHTML.create('gym', Preferences.get('gym'))}
|
||||
<span>Gimnasio</span>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
${CheckboxHTML.create('pool', Preferences.get('pool'))}
|
||||
<span>Piscina</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class='${ButtonClass.IDEALISTA_BUTTON_CLASS} ${this.SAVE_CONFIG_CLASS_NAME}'>Guardar</button>
|
||||
<button class='${ButtonClass.IDEALISTA_BUTTON_CLASS} ${this.OPEN_CONFIG_CLASS_NAME}'>Cerrar</button>
|
||||
|
14
src/Event.js
14
src/Event.js
@ -1,11 +1,21 @@
|
||||
import Log from "./Log.js";
|
||||
import StringUtil from "./StringUtil.js";
|
||||
|
||||
export default class Event {
|
||||
|
||||
static click(selector, callback) {
|
||||
document.addEventListener('click', (event) => {
|
||||
this._addEvent('click', selector, callback)
|
||||
}
|
||||
|
||||
static change(selector, callback) {
|
||||
this._addEvent('change', selector, callback)
|
||||
}
|
||||
|
||||
static _addEvent(eventName, selector, callback) {
|
||||
Log.debug(`Adding event: ${eventName} to: ${selector}`);
|
||||
document.addEventListener(eventName, (event) => {
|
||||
if (!event.target.matches(selector)) return;
|
||||
Log.debug(`Click on: ${selector}`)
|
||||
Log.debug(`${StringUtil.capitalizeFirstLetter(eventName)} on: ${selector}`);
|
||||
callback(event.target);
|
||||
});
|
||||
}
|
||||
|
19
src/Item.js
19
src/Item.js
@ -14,6 +14,10 @@ export default class Item {
|
||||
this._node = htmlNode;
|
||||
|
||||
this.name = this._extractName();
|
||||
|
||||
this.locationName = this._extractLocationName();
|
||||
//this.location = this._extractLocation();
|
||||
|
||||
this.price = this._extractPrice();
|
||||
this.meters = this._extractMeters();
|
||||
this.priceMeter = this._extractPriceMeter();
|
||||
@ -77,12 +81,18 @@ export default class Item {
|
||||
}
|
||||
|
||||
_extractName() {
|
||||
return this._node.querySelector(Item.NAME_SELECTOR).textContent;;
|
||||
return this._node.querySelector(Item.NAME_SELECTOR).textContent;
|
||||
}
|
||||
|
||||
_extractLocationName() {
|
||||
return this.name
|
||||
.substring(this.name.lastIndexOf(','), this.name.length)
|
||||
.replaceAll('.', '').replaceAll(',', '');
|
||||
}
|
||||
|
||||
_extractPrice() {
|
||||
const priceText = this._node.querySelector(Item.PRICE_SELECTOR).textContent;
|
||||
return Number(priceText.replace('€', '').replace('.', '').replace(',', ''));
|
||||
return Number(priceText.replace('€', '').replaceAll('.', '').replaceAll(',', ''));
|
||||
}
|
||||
|
||||
_extractMeters() {
|
||||
@ -90,7 +100,10 @@ export default class Item {
|
||||
if (!metersText.includes('m²')) {
|
||||
metersText = this._node.querySelector(Item.ROOM_SELECTOR).textContent;
|
||||
}
|
||||
return Number(metersText.replace('m²', ''));
|
||||
return Number(metersText
|
||||
.replace('m²', '')
|
||||
.replaceAll('.', '')
|
||||
);
|
||||
}
|
||||
|
||||
_extractPriceMeter() {
|
||||
|
@ -7,6 +7,7 @@ export default class ItemHTML {
|
||||
static ERROR_CLASS_NAME = 'error';
|
||||
|
||||
static CONTAINER_CLASS_NAME = 'midefos-idealista-container';
|
||||
static INFORMATION_CONTAINER_CLASS_NAME = 'midefos-idealista-information-container';
|
||||
static get CONTAINER_SELECTOR() {
|
||||
return `.${this.CONTAINER_CLASS_NAME}`;
|
||||
}
|
||||
@ -44,27 +45,42 @@ export default class ItemHTML {
|
||||
static createInformation(item) {
|
||||
return `
|
||||
<div class='${this.CONTAINER_CLASS_NAME} ${this.ITEM_STATE_CLASS_NAME(item)}'>
|
||||
${this._createPercentagePriceHTML(item)}
|
||||
${this._createPriceHTML(item)}
|
||||
${this._createPriceMeterHTML(item)}
|
||||
${this._createGarageHTML(item)}
|
||||
${this._createLiftHTML(item)}
|
||||
${this._createExteriorHTML(item)}
|
||||
<div class='${this.INFORMATION_CONTAINER_CLASS_NAME}'>
|
||||
${this._createPercentagePriceHTML(item)}
|
||||
${this._createPriceHTML(item)}
|
||||
${this._createPriceMeterHTML(item)}
|
||||
${this._createGarageHTML(item)}
|
||||
${this._createLiftHTML(item)}
|
||||
${this._createExteriorHTML(item)}
|
||||
</div>
|
||||
<div class='${this.INFORMATION_CONTAINER_CLASS_NAME}'>
|
||||
${this._createLocationInformation(item)}
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
static _createPercentagePriceHTML(item) {
|
||||
if (!Preferences.get('percentages')) return ``;
|
||||
|
||||
const twentyPercent = Math.round(item.price * 20 / 100);
|
||||
const thirtyPercent = Math.round(item.price * 30 / 100);
|
||||
const fiftyPercent = Math.round(item.price * 50 / 100);
|
||||
return `
|
||||
<div class='${this.INFORMATION_CLASS_NAME}'>
|
||||
${this._createIndividual('20%', twentyPercent)}
|
||||
${this._createIndividual('30%', thirtyPercent)}
|
||||
${this._createIndividual('50%', fiftyPercent)}
|
||||
</div>`;
|
||||
|
||||
let html = `<div class='${this.INFORMATION_CLASS_NAME}'>`;
|
||||
if (Preferences.get('percentages_20')) {
|
||||
const twentyPercent = Math.round(item.price * 20 / 100);
|
||||
html += this._createIndividual('20%', twentyPercent);
|
||||
}
|
||||
|
||||
if (Preferences.get('percentages_30')) {
|
||||
const thirtyPercent = Math.round(item.price * 30 / 100);
|
||||
html += this._createIndividual('30%', thirtyPercent)
|
||||
}
|
||||
|
||||
if (Preferences.get('percentages_50')) {
|
||||
const fiftyPercent = Math.round(item.price * 50 / 100);
|
||||
html += this._createIndividual('50%', fiftyPercent)
|
||||
}
|
||||
html += `</div>`;
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
static _createPriceHTML(item) {
|
||||
@ -146,6 +162,10 @@ export default class ItemHTML {
|
||||
return this._createMissing('Exterior');
|
||||
}
|
||||
|
||||
static _createLocationInformation(item) {
|
||||
return this._createNeutral(item.locationName);
|
||||
}
|
||||
|
||||
static _shouldCheckExterior(item) {
|
||||
return Preferences.get('exterior')
|
||||
&& !item.isHouse();
|
||||
|
14
src/Location.js
Normal file
14
src/Location.js
Normal file
@ -0,0 +1,14 @@
|
||||
export default class Location {
|
||||
|
||||
name;
|
||||
|
||||
train;
|
||||
bus;
|
||||
|
||||
pool;
|
||||
gym;
|
||||
|
||||
supermarkets;
|
||||
smoke;
|
||||
|
||||
}
|
42
src/Locations.js
Normal file
42
src/Locations.js
Normal file
@ -0,0 +1,42 @@
|
||||
import Location from './Location.js';
|
||||
import Supermarket from './Supermarket.js';
|
||||
|
||||
export default class Locations {
|
||||
|
||||
static get ZARAGOZA() {
|
||||
const location = new Location();
|
||||
location.name = 'Zaragoza';
|
||||
|
||||
location.bus = true;
|
||||
location.train = true;
|
||||
|
||||
location.pool = true;
|
||||
location.gym = true;
|
||||
|
||||
location.supermarkets = [
|
||||
Supermarket.DIA('https://goo.gl/maps/NLCXd7GdYWS2wgBMA')
|
||||
];
|
||||
location.smoke = true;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
static get BIELSA() {
|
||||
const location = new Location();
|
||||
location.name = 'Bielsa';
|
||||
|
||||
location.bus = true;
|
||||
location.train = false;
|
||||
|
||||
location.pool = false;
|
||||
location.gym = true;
|
||||
|
||||
location.supermarkets = [
|
||||
Supermarket.SPAR('https://goo.gl/maps/KGhqH8SwMJrcwPse8')
|
||||
];
|
||||
location.smoke = true;
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
@ -12,7 +12,9 @@ export default class Preferences {
|
||||
|
||||
static get(key) {
|
||||
const config = this._getConfig();
|
||||
return config[key];
|
||||
const value = config[key];
|
||||
if (value === undefined) return this._getFromDefault(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
static save(config) {
|
||||
@ -33,15 +35,33 @@ export default class Preferences {
|
||||
return JSON.parse(storageConfig);
|
||||
}
|
||||
|
||||
static _getFromDefault(key) {
|
||||
const defaultPreferences = this._default();
|
||||
return defaultPreferences[key];
|
||||
}
|
||||
|
||||
static _default() {
|
||||
return {
|
||||
enabled: true,
|
||||
|
||||
'max-price': 120_000,
|
||||
'max-price-per-meter': 1_500,
|
||||
percentages: true,
|
||||
percentages_20: true,
|
||||
percentages_30: true,
|
||||
percentages_50: false,
|
||||
|
||||
garage: false,
|
||||
exterior: true,
|
||||
lift: true,
|
||||
'max-price': 120_000,
|
||||
'max-price-per-meter': 1_500
|
||||
|
||||
bus: false,
|
||||
train: false,
|
||||
supermarket: true,
|
||||
smoke: false,
|
||||
pharmacy: true,
|
||||
gym: false,
|
||||
pool: true
|
||||
}
|
||||
}
|
||||
|
||||
|
7
src/StringUtil.js
Normal file
7
src/StringUtil.js
Normal file
@ -0,0 +1,7 @@
|
||||
export default class StringUtil {
|
||||
|
||||
static capitalizeFirstLetter(string) {
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
}
|
@ -5,10 +5,19 @@ import MenuHTML from "./MenuHTML.js";
|
||||
export default class Styles {
|
||||
|
||||
static APP_STYLES = `
|
||||
|
||||
.midefos-idealista-card {
|
||||
box-shadow: 0px 0px 8px -1px rgba(0,0,0,0.35);
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.${ItemHTML.CONTAINER_CLASS_NAME} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
margin-top: -10px;
|
||||
@ -20,12 +29,20 @@ export default class Styles {
|
||||
border: 3px solid transparent;
|
||||
}
|
||||
|
||||
.${ItemHTML.INFORMATION_CONTAINER_CLASS_NAME} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.${ItemHTML.INFORMATION_CLASS_NAME} {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.${ItemHTML.SUCCESS_CLASS_NAME} {
|
||||
span.${ItemHTML.SUCCESS_CLASS_NAME} {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
@ -33,11 +50,11 @@ export default class Styles {
|
||||
border-color: rgba(61, 217, 61, 0.3);
|
||||
}
|
||||
|
||||
.${ItemHTML.WARNING_CLASS_NAME} {
|
||||
span.${ItemHTML.WARNING_CLASS_NAME} {
|
||||
color: darkorange;
|
||||
}
|
||||
|
||||
.${ItemHTML.ERROR_CLASS_NAME} {
|
||||
span.${ItemHTML.ERROR_CLASS_NAME} {
|
||||
color: darkred;
|
||||
}
|
||||
|
||||
@ -72,6 +89,10 @@ export default class Styles {
|
||||
border: 5px solid rgb(225, 245, 110);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.${ConfigurationHTML.CONTAINER_CLASS_NAME} label {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
static add(style = null) {
|
||||
|
47
src/Supermarket.js
Normal file
47
src/Supermarket.js
Normal file
@ -0,0 +1,47 @@
|
||||
export default class Supermarket {
|
||||
|
||||
name;
|
||||
url;
|
||||
|
||||
constructor(name, url) {
|
||||
this.name = name;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
static DIA(url) {
|
||||
return new Supermarket('Dia', url);
|
||||
}
|
||||
|
||||
static MERCADONA(url) {
|
||||
return new Supermarket('Mercadona', url);
|
||||
}
|
||||
|
||||
static LIDL(url) {
|
||||
return new Supermarket('Lidl', url);
|
||||
}
|
||||
|
||||
static CARREFOUR(url) {
|
||||
return new Supermarket('Carrefour', url);
|
||||
}
|
||||
|
||||
static SPAR(url) {
|
||||
return new Supermarket('Spar', url);
|
||||
}
|
||||
|
||||
static EROSKI(url) {
|
||||
return new Supermarket('Eroski', url);
|
||||
}
|
||||
|
||||
static SUMA(url) {
|
||||
return new Supermarket('Suma', url);
|
||||
}
|
||||
|
||||
static SIMPLY(url) {
|
||||
return new Supermarket('Simply', url);
|
||||
}
|
||||
|
||||
static CUSTOM(url) {
|
||||
return new Supermarket('Custom', url);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user