Separating code into files.
Bundling the code with node. Adding some neccesary files.
This commit is contained in:
45
src/Configuration.js
Normal file
45
src/Configuration.js
Normal file
@ -0,0 +1,45 @@
|
||||
export default class Configuration {
|
||||
|
||||
static NAME = 'midefos-idealista';
|
||||
|
||||
static _current;
|
||||
|
||||
static init() {
|
||||
this._current = this._getConfig();
|
||||
}
|
||||
|
||||
static get(key) {
|
||||
const config = this._getConfig();
|
||||
return config[key];
|
||||
}
|
||||
|
||||
static save(config) {
|
||||
window.localStorage.setItem(this.NAME, JSON.stringify(config));
|
||||
this._current = config;
|
||||
}
|
||||
|
||||
static _getConfig() {
|
||||
const storageConfig = this._getFromLocalStorage();
|
||||
if (!storageConfig) return this._default();
|
||||
return storageConfig;
|
||||
}
|
||||
|
||||
static _getFromLocalStorage() {
|
||||
const storageConfig = window.localStorage.getItem(this.NAME);
|
||||
if (!storageConfig) return null;
|
||||
return JSON.parse(storageConfig);
|
||||
}
|
||||
|
||||
static _default() {
|
||||
return {
|
||||
enabled: true,
|
||||
percentages: true,
|
||||
garage: false,
|
||||
exterior: true,
|
||||
lift: true,
|
||||
'max-price': 120_000,
|
||||
'max-price-per-meter': 1_500
|
||||
}
|
||||
}
|
||||
|
||||
}
|
71
src/Item.js
Normal file
71
src/Item.js
Normal file
@ -0,0 +1,71 @@
|
||||
export default class Item {
|
||||
|
||||
static NAME_SELECTOR = '.item-link';
|
||||
static PRICE_SELECTOR = '.item-price';
|
||||
static ROOM_SELECTOR = '.item-detail-char .item-detail:nth-child(1)';
|
||||
static METERS_SELECTOR = '.item-detail-char .item-detail:nth-child(2)';
|
||||
static ADDITIONAL_INFORMATION_SELECTOR = '.item-detail-char .item-detail:nth-child(3)';
|
||||
|
||||
constructor(htmlNode) {
|
||||
this._node = htmlNode;
|
||||
|
||||
this.name = this._extractName();
|
||||
this.price = this._extractPrice();
|
||||
this.meters = this._extractMeters();
|
||||
this.priceMeter = this._extractPriceMeter();
|
||||
|
||||
this.additionalInfo = this._extractAdditionalInfo();
|
||||
this.hasLift = this._extractLift();
|
||||
this.isExterior = this._extractExterior();
|
||||
}
|
||||
|
||||
_extractName() {
|
||||
return this._node.querySelector(Item.NAME_SELECTOR).textContent;;
|
||||
}
|
||||
|
||||
_extractPrice() {
|
||||
const priceText = this._node.querySelector(Item.PRICE_SELECTOR).textContent;
|
||||
return Number(priceText.replace('€', '').replace('.', '').replace(',', ''));
|
||||
}
|
||||
|
||||
_extractMeters() {
|
||||
let metersText = this._node.querySelector(Item.METERS_SELECTOR).textContent;
|
||||
if (!metersText.includes('m²')) {
|
||||
metersText = this._node.querySelector(Item.ROOM_SELECTOR).textContent;
|
||||
}
|
||||
return Number(metersText.replace('m²', ''));
|
||||
}
|
||||
|
||||
_extractPriceMeter() {
|
||||
return Math.round(this.price / this.meters);
|
||||
}
|
||||
|
||||
_extractAdditionalInfo() {
|
||||
const additionalInfo = this._node.querySelector(Item.ADDITIONAL_INFORMATION_SELECTOR);
|
||||
if (!additionalInfo) return null;
|
||||
return additionalInfo.textContent;
|
||||
}
|
||||
|
||||
_extractLift() {
|
||||
if (!this.additionalInfo) return false;
|
||||
return this.additionalInfo.includes('con ascensor');
|
||||
}
|
||||
|
||||
_extractExterior() {
|
||||
if (!this.additionalInfo) return false;
|
||||
return this.additionalInfo.includes('exterior');
|
||||
}
|
||||
|
||||
isFlat() {
|
||||
return this.name.includes('Piso');
|
||||
}
|
||||
|
||||
isHouse() {
|
||||
return this.name.includes('Casa');
|
||||
}
|
||||
|
||||
isGround() {
|
||||
return this.name.includes('Bajo');
|
||||
}
|
||||
|
||||
}
|
87
src/ItemHTML.js
Normal file
87
src/ItemHTML.js
Normal file
@ -0,0 +1,87 @@
|
||||
import Configuration from "./Configuration.js";
|
||||
|
||||
export default class ItemHTML {
|
||||
|
||||
|
||||
static createInformation(item) {
|
||||
return `
|
||||
<div class='midefos-idealista-container'>
|
||||
${this._createPercentagePriceHTML(item)}
|
||||
${this._createPriceHTML(item)}
|
||||
${this._createPriceMeterHTML(item)}
|
||||
${this._createLiftHTML(item)}
|
||||
${this._createInteriorHTML(item)}
|
||||
</div>`
|
||||
}
|
||||
|
||||
static _createPercentagePriceHTML(item) {
|
||||
if (!Configuration.get('percentages')) return ``;
|
||||
|
||||
const twentyPercent = Math.round(item.price * 20 / 100);
|
||||
const thirtyPercent = Math.round(item.price * 30 / 100);
|
||||
return `
|
||||
<span>
|
||||
<strong>20%:</strong> ${twentyPercent}€ <br>
|
||||
<strong>30%:</strong> ${thirtyPercent}€
|
||||
</span>`;
|
||||
}
|
||||
|
||||
|
||||
static _createPriceHTML(item) {
|
||||
const desiredPrice = Configuration.get('max-price');
|
||||
const desiredTwentyFivePercentMore = Math.round(desiredPrice * 1.25);
|
||||
|
||||
if (item.price <= desiredPrice) {
|
||||
return `<span class='success'><strong>✓</strong> Precio</span>`;
|
||||
} else if (item.price <= desiredTwentyFivePercentMore) {
|
||||
return `<span class='warning'><strong>✓</strong> Precio</span>`;
|
||||
}
|
||||
return `<span class='error'><strong>X</strong> Precio</span>`;
|
||||
}
|
||||
|
||||
|
||||
static _createPriceMeterHTML(item) {
|
||||
const desiredPricePerMeter = Configuration.get('max-price-per-meter');
|
||||
const desiredTwentyFivePercentMore = Math.round(desiredPricePerMeter * 1.25);
|
||||
|
||||
if (item.priceMeter <= desiredPricePerMeter) {
|
||||
return `<span class='success'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
} else if (item.priceMeter <= desiredTwentyFivePercentMore) {
|
||||
return `<span class='warning'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
}
|
||||
return `<span class='error'><strong>m²:</strong> ${item.priceMeter}€</span>`;
|
||||
}
|
||||
|
||||
static _createLiftHTML(item) {
|
||||
if (!Configuration.get('lift')) return ``;
|
||||
|
||||
if (!item.additionalInfo) {
|
||||
if (item.isFlat()) return ``;
|
||||
return this.__createIndividual('?', 'Ascensor', 'warning');
|
||||
}
|
||||
|
||||
if (item.hasLift) {
|
||||
return this.__createIndividual('✓', 'Ascensor', 'warning');
|
||||
}
|
||||
return this.__createIndividual('X', 'Ascensor', 'error');
|
||||
}
|
||||
|
||||
static _createInteriorHTML(item) {
|
||||
if (!Configuration.get('exterior')) return ``;
|
||||
|
||||
if (!item.additionalInfo) {
|
||||
if (!item.isFlat()) return ``;
|
||||
return `<span class='warning'><strong>?</strong> Exterior</span>`
|
||||
}
|
||||
|
||||
if (item.isExterior) {
|
||||
return `<span class='success'><strong>✓</strong> Exterior</span>`
|
||||
}
|
||||
return `<span class='error'><strong>X</strong> Exterior</span>`;
|
||||
}
|
||||
|
||||
static __createIndividual(strongText, infoText, className = '') {
|
||||
return `<span class='${className}'><strong>${strongText}</strong> ${infoText}</span>`;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user