aboutsummaryrefslogtreecommitdiffstats
path: root/app/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/main.js')
-rw-r--r--app/main.js209
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;
}
}