diff options
Diffstat (limited to 'app/main.js')
| -rw-r--r-- | app/main.js | 209 |
1 files changed, 73 insertions, 136 deletions
diff --git a/app/main.js b/app/main.js index 3995a07..f4227d9 100644 --- a/app/main.js +++ b/app/main.js @@ -2,12 +2,14 @@ import { Modal, Sidebar } from "components"; import { Dom, DomOptions } from "dom"; -import { AreaColorParameter, ColorParameter, MapEl } from "map"; +import { MapEl } from "map"; import { - DataProvider, + AreaParam, + Collection, District, Filters, House, + HouseParameter, ScoringEngine, StatisticalArea, TrainStation, @@ -18,20 +20,14 @@ import { export class App { /** @type {House[]} */ #houses = []; - /** @type {TrainTracks[]} */ - #trainTracks = []; - /** @type {TrainStation[]} */ - #trainStations = []; - /** @type {StatisticalArea[]} */ - #statAreas = []; + /** @type {Collection|null} */ + collection = null; /** @type {House[]} */ #filtered = []; /** @type {Filters} */ #filters = new Filters(); /** @type {Weights} */ #weights = new Weights(); - /** @type {District[]} */ - #districts = []; /** @type {MapEl} */ #map; /** @type {HTMLElement} */ @@ -42,10 +38,10 @@ export class App { #modal = null; /** @type {boolean} */ #persistent = false; - /** @type {string} */ - #colorParameter = ColorParameter.price; - /** @type {string} */ - #areaColorParameter = AreaColorParameter.unemploymentRate; + /** @type {HouseParameter} */ + #houseParameter = HouseParameter.price; + /** @type {AreaParam} */ + #areaParameter = AreaParam.unemploymentRate; constructor() { // Set up main layout container @@ -61,10 +57,33 @@ export class App { this.#sidebar = new Sidebar( this.#filters, this.#weights, - () => this.#onFilterChange(), - (key, value) => this.#onWeightChange(key, value), - (param) => this.#onColorChange(param), - (param) => this.#onAreaColorChange(param), + () => { + this.#filtered = this.#houses.filter((h) => h.matchesFilters(this.#filters)); + const filteredIds = this.#filtered.map((h) => h.id); + this.#map.updateHouseVisibility(filteredIds); + + const stats = App.#getStats(this.#filtered); + this.#stats.replaceWith(stats); + this.#stats = stats; + }, + (key, value) => { + if (key in this.#weights) { + this.#weights[/** @type {keyof Weights} */ (key)] = value; + } + App.#recalculateScores(this.#houses, this.#weights); + this.#map.updateHousesColor(this.#houseParameter); + const stats = App.#getStats(this.#filtered); + this.#stats.replaceWith(stats); + this.#stats = stats; + }, + (param) => { + this.#houseParameter = param; + this.#map.updateHousesColor(this.#houseParameter); + }, + (param) => { + this.#areaParameter = param; + this.#map.updateArea(this.#areaParameter); + }, ); this.#map = new MapEl({ @@ -78,19 +97,6 @@ export class App { }, }); - this.#stats = Dom.div( - new DomOptions({ - id: "stats", - styles: { - background: "#fff", - borderTop: "1px solid #ddd", - flexShrink: "0", - fontSize: "0.95rem", - padding: "0.75rem 1rem", - }, - }), - ); - const loading = Dom.span( "Loading data…", new DomOptions({ @@ -112,6 +118,7 @@ export class App { }), ); + this.#stats = App.#getStats(this.#filtered); document.body.append( loading, Dom.div( @@ -144,50 +151,6 @@ export class App { } /** - * Handle filter changes - */ - #onFilterChange() { - this.#filtered = this.#houses.filter((h) => h.matchesFilters(this.#filters)); - if (this.#map) { - const filteredIds = this.#filtered.map((h) => h.id); - this.#map.updateHouseVisibility(filteredIds); - } - this.#updateStats(); - } - - /** - * Handle weight changes - * @param {string} key - * @param {number} value - */ - #onWeightChange(key, value) { - if (key in this.#weights) { - this.#weights[/** @type {keyof Weights} */ (key)] = value; - } - App.#recalculateScores(this.#houses, this.#weights); - this.#map?.setColorParameter(this.#colorParameter); - this.#updateStats(); - } - - /** - * Handle color parameter changes - * @param {string} param - */ - #onColorChange(param) { - this.#colorParameter = param; - this.#map?.setColorParameter(this.#colorParameter); - } - - /** - * Handle area color parameter changes - * @param {string} param - */ - #onAreaColorChange(param) { - this.#areaColorParameter = param; - this.#map?.setAreaColorParameter(this.#areaColorParameter); - } - - /** * Show modal with house details * @param {string} houseId * @param {boolean} persistent @@ -197,9 +160,7 @@ export class App { if (!house) return; this.#persistent = persistent; - if (this.#map) { - this.#map.setModalPersistence(persistent); - } + this.#map.setModalPersistence(persistent); // Hide existing modal this.#modal?.hide(); @@ -219,15 +180,11 @@ export class App { () => { this.#modal = null; this.#persistent = false; - if (this.#map) { - this.#map.setModalPersistence(false); - this.#map.clearModalTimer(); - } + this.#map.setModalPersistence(false); + this.#map.clearModalTimer(); }, () => { - if (this.#map) { - this.#map.clearModalTimer(); - } + this.#map.clearModalTimer(); }, ); @@ -241,43 +198,16 @@ export class App { */ async #initialize(loading) { try { - const [districts, houses, trainStations, trainTracks, coastLine, mainRoads, statAreas] = - await Promise.all([ - DataProvider.getDistricts(), - DataProvider.getHouses(), - DataProvider.getTrainStations(), - DataProvider.getTrainTracks(), - DataProvider.getCoastline(), - DataProvider.getMainRoads(), - DataProvider.getStatisticalAreas(), - ]); - this.#districts = districts; - this.#houses = houses; - this.#trainStations = trainStations; - this.#trainTracks = trainTracks; - this.#statAreas = statAreas; - - this.#filtered = houses.slice(); + this.collection = await Collection.get(); + this.#filtered = this.collection.houses.slice(); + this.#map.initialize(this.collection, this.#houseParameter, this.#areaParameter); - this.#map.initialize( - districts, - coastLine, - mainRoads, - trainTracks, - trainStations, - houses, - statAreas, - this.#colorParameter, - ); + this.#sidebar.updateDistricts(this.#houses); + this.#sidebar.setAreaColorParameter(this.#areaParameter); - // Set default area coloring to unemployment rate - this.#map.setAreaColorParameter(this.#areaColorParameter); - - // Update sidebar with districts and area color parameter - this.#sidebar.updateDistricts(this.#districts, this.#houses); - this.#sidebar.setAreaColorParameter(this.#areaColorParameter); - - this.#updateStats(); + const stats = App.#getStats(this.#filtered); + this.#stats.replaceWith(stats); + this.#stats = stats; } finally { loading.remove(); } @@ -296,30 +226,37 @@ export class App { /** * Update statistics display using DOM methods + * @param {House[]} filtered */ - #updateStats() { - const count = this.#filtered.length; - const avg = count - ? Math.round(this.#filtered.reduce((s, h) => s + h.scores.current, 0) / count) - : 0; - - // Clear existing content - this.#stats.innerHTML = ""; - - // Create elements using DOM methods - const countStrong = document.createElement("strong"); - countStrong.textContent = count.toString(); - - const avgStrong = document.createElement("strong"); - avgStrong.textContent = avg.toString(); + static #getStats(filtered) { + const stats = Dom.div( + new DomOptions({ + id: "stats", + styles: { + background: "#fff", + borderTop: "1px solid #ddd", + flexShrink: "0", + fontSize: "0.95rem", + padding: "0.75rem 1rem", + }, + }), + ); + const countStrong = Dom.strong(filtered.length.toString()); + const avgStrong = Dom.strong( + (filtered.length + ? Math.round(filtered.reduce((s, h) => s + h.scores.current, 0) / filtered.length) + : 0 + ).toString(), + ); // Append all elements - this.#stats.append( + stats.append( countStrong, document.createTextNode(" houses shown • Average score: "), avgStrong, document.createTextNode(" • Use weights sliders to adjust scoring"), ); + return stats; } } |
