diff options
Diffstat (limited to 'app/main.js')
| -rw-r--r-- | app/main.js | 454 |
1 files changed, 213 insertions, 241 deletions
diff --git a/app/main.js b/app/main.js index ef51345..4ccebe0 100644 --- a/app/main.js +++ b/app/main.js @@ -1,7 +1,7 @@ -// main.js - Updated with Sidebar class +// main.js - Updated with Sidebar class and new Dom interface -import { LeftSidebar, Modal, RightSidebar } from "components"; -import { Dom, DomOptions } from "dom"; +import { BottomBar, LeftSidebar, Modal, RightSidebar } from "components"; +import { Dom } from "dom"; import { MapEl } from "map"; import { AreaParam, @@ -20,67 +20,57 @@ export class Init { #collection = null; constructor() { - this.#loadingElement = Dom.div( - new DomOptions({ - children: [ - Dom.div( - new DomOptions({ - children: [ - Dom.span( - "🏠", - new DomOptions({ - styles: { - fontSize: "3rem", - marginBottom: "1rem", - }, - }), - ), - Dom.span( - "Loading Housing Application...", - new DomOptions({ - styles: { - color: "#333", - fontSize: "1.2rem", - fontWeight: "500", - }, - }), - ), - Dom.span( - "Please wait while we load and process the data", - new DomOptions({ - styles: { - color: "#666", - fontSize: "0.9rem", - marginTop: "0.5rem", - }, - }), - ), - ], + this.#loadingElement = Dom.div({ + children: [ + Dom.div({ + children: [ + Dom.span({ styles: { - alignItems: "center", - display: "flex", - flexDirection: "column", - textAlign: "center", + fontSize: "3rem", + marginBottom: "1rem", }, + text: "🏠", }), - ), - ], - styles: { - alignItems: "center", - background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", - color: "white", - display: "flex", - fontFamily: "Roboto Mono, monospace", - height: "100%", - justifyContent: "center", - left: "0", - position: "fixed", - top: "0", - width: "100%", - zIndex: "9999", - }, - }), - ); + Dom.span({ + styles: { + color: "#333", + fontSize: "1.2rem", + fontWeight: "500", + }, + text: "Loading Housing Application...", + }), + Dom.span({ + styles: { + color: "#666", + fontSize: "0.9rem", + marginTop: "0.5rem", + }, + text: "Please wait while we load and process the data", + }), + ], + styles: { + alignItems: "center", + display: "flex", + flexDirection: "column", + textAlign: "center", + }, + }), + ], + styles: { + alignItems: "center", + background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", + color: "white", + display: "flex", + fontFamily: "Roboto Mono, monospace", + height: "100%", + justifyContent: "center", + left: "0", + position: "fixed", + top: "0", + width: "100%", + zIndex: "9999", + }, + }); document.body.appendChild(this.#loadingElement); Object.assign(document.body.style, { @@ -120,86 +110,74 @@ export class Init { * @param {string} message */ static getError(message) { - return Dom.div( - new DomOptions({ - children: [ - Dom.div( - new DomOptions({ - children: [ - Dom.span( - "❌", - new DomOptions({ - styles: { - fontSize: "3rem", - marginBottom: "1rem", - }, - }), - ), - Dom.span( - "Application Error", - new DomOptions({ - styles: { - color: "#c53030", - fontSize: "1.5rem", - fontWeight: "bold", - marginBottom: "1rem", - }, - }), - ), - Dom.span( - message, - new DomOptions({ - styles: { - color: "#744210", - fontSize: "1rem", - lineHeight: "1.5", - marginBottom: "2rem", - textAlign: "center", - }, - }), - ), - Dom.button( - "Refresh Page", - () => location.reload(), - new DomOptions({ - styles: { - background: "#c53030", - border: "none", - borderRadius: "6px", - color: "white", - cursor: "pointer", - fontSize: "1rem", - padding: "0.75rem 1.5rem", - transition: "background-color 0.2s", - }, - }), - ), - ], + return Dom.div({ + children: [ + Dom.div({ + children: [ + Dom.span({ + styles: { + fontSize: "3rem", + marginBottom: "1rem", + }, + text: "❌", + }), + Dom.span({ styles: { - alignItems: "center", - display: "flex", - flexDirection: "column", - maxWidth: "400px", + color: "#c53030", + fontSize: "1.5rem", + fontWeight: "bold", + marginBottom: "1rem", + }, + text: "Application Error", + }), + Dom.span({ + styles: { + color: "#744210", + fontSize: "1rem", + lineHeight: "1.5", + marginBottom: "2rem", textAlign: "center", }, + text: message, }), - ), - ], - styles: { - alignItems: "center", - background: "#fed7d7", - display: "flex", - fontFamily: "Roboto Mono, monospace", - height: "100%", - justifyContent: "center", - left: "0", - position: "fixed", - top: "0", - width: "100%", - zIndex: "9999", - }, - }), - ); + Dom.button({ + onClick: () => location.reload(), + styles: { + background: "#c53030", + border: "none", + borderRadius: "6px", + color: "white", + cursor: "pointer", + fontSize: "1rem", + padding: "0.75rem 1.5rem", + transition: "background-color 0.2s", + }, + text: "Refresh Page", + }), + ], + styles: { + alignItems: "center", + display: "flex", + flexDirection: "column", + maxWidth: "400px", + textAlign: "center", + }, + }), + ], + styles: { + alignItems: "center", + background: "#fed7d7", + display: "flex", + fontFamily: "Roboto Mono, monospace", + height: "100%", + justifyContent: "center", + left: "0", + position: "fixed", + top: "0", + width: "100%", + zIndex: "9999", + }, + }); } /** @@ -233,6 +211,8 @@ export class App { #houseParameter = HouseParameter.price; /** @type {AreaParam} */ #areaParameter = AreaParam.unemploymentRate; + /** @type {BottomBar} */ + #bottomBar; /** * @param {Collection} collection @@ -242,6 +222,11 @@ export class App { this.#collection = collection; this.#filters = filters; + this.#bottomBar = new BottomBar({ + houses: this.#collection.houses.sort((a, b) => b.scores.current - a.scores.current), + onHouseClick: (houseId) => this.#showHouseModal(houseId, true), + }); + Object.assign(document.body.style, { display: "flex", flexDirection: "column", @@ -251,51 +236,48 @@ export class App { }); // Create header with global toggle buttons - const header = Dom.div( - new DomOptions({ - children: [ - // Left sidebar toggle button - Dom.button( - "☰ Filters", - () => this.#leftSidebar.toggle(), - new DomOptions({ - styles: { - background: "#fff", - border: "1px solid #ddd", - borderRadius: "4px", - cursor: "pointer", - fontSize: "1rem", - margin: "0.5rem", - padding: "0.5rem 1rem", - }, - }), - ), - // Right sidebar toggle button - Dom.button( - "⚙️ Weights", - () => this.#rightSidebar.toggle(), - new DomOptions({ - styles: { - background: "#fff", - border: "1px solid #ddd", - borderRadius: "4px", - cursor: "pointer", - fontSize: "1rem", - margin: "0.5rem", - padding: "0.5rem 1rem", - }, - }), - ), - ], - styles: { - background: "#f5f5f5", - borderBottom: "1px solid #ddd", - display: "flex", - justifyContent: "space-between", - padding: "0", - }, - }), - ); + const header = Dom.div({ + children: [ + // Left sidebar toggle button + Dom.button({ + onClick: () => this.#leftSidebar.toggle(), + styles: { + background: "#fff", + border: "1px solid #ddd", + borderRadius: "4px", + cursor: "pointer", + fontSize: "1rem", + margin: "0.5rem", + padding: "0.5rem 1rem", + }, + text: "☰ Filters", + }), + // Right sidebar toggle button + Dom.button({ + onClick: () => { + this.#bottomBar.show(); + this.#rightSidebar.toggle(); + }, + styles: { + background: "#fff", + border: "1px solid #ddd", + borderRadius: "4px", + cursor: "pointer", + fontSize: "1rem", + margin: "0.5rem", + padding: "0.5rem 1rem", + }, + text: "⚙️ Weights", + }), + ], + styles: { + background: "#f5f5f5", + borderBottom: "1px solid #ddd", + display: "flex", + justifyContent: "space-between", + padding: "0", + }, + }); this.#leftSidebar = new LeftSidebar({ allHouses: this.#collection.houses, @@ -339,55 +321,52 @@ export class App { areaParameter: this.#areaParameter, collection: this.#collection, houseParameter: this.#houseParameter, + /** @param {string} houseId @param {boolean} persistent */ onHouseClick: (houseId, persistent) => this.#showHouseModal(houseId, persistent), + /** @param {string} houseId @param {boolean} hide */ onHouseHover: (houseId, hide) => { - hide ? this.#modal?.hide() : this.#showHouseModal(houseId, false); + hide ? this.#modal?.remove() : this.#showHouseModal(houseId, false); }, }); this.#stats = App.#createStats(this.#collection.houses, this.#filters); document.body.appendChild( - Dom.div( - new DomOptions({ - children: [ - header, - Dom.div( - new DomOptions({ - children: [ - this.#leftSidebar.render(), - Dom.div( - new DomOptions({ - children: [this.#map.svg, this.#stats], - id: "map-container", - styles: { - display: "flex", - flex: "1", - flexDirection: "column", - minWidth: "0", - }, - }), - ), - this.#rightSidebar.render(), - ], - id: "main-content", + Dom.div({ + children: [ + header, + Dom.div({ + children: [ + this.#leftSidebar.render(), + Dom.div({ + children: [this.#map.svg, this.#stats], + id: "map-container", styles: { display: "flex", flex: "1", - height: "calc(100vh - 60px)", - overflow: "hidden", + flexDirection: "column", + minWidth: "0", }, }), - ), - ], - id: "main", - styles: { - display: "flex", - flexDirection: "column", - height: "100vh", - }, - }), - ), + this.#rightSidebar.render(), + this.#bottomBar.render(), + ], + id: "main-content", + styles: { + display: "flex", + flex: "1", + height: "calc(100vh - 60px)", + overflow: "hidden", + }, + }), + ], + id: "main", + styles: { + display: "flex", + flexDirection: "column", + height: "100vh", + }, + }), ); } @@ -430,11 +409,6 @@ export class App { } /** - * Apply filters and recalculate scores - */ - #applyFiltersAndScoring() {} - - /** * Create statistics display * @param {House[]} houses * @param {Filters} filters @@ -446,24 +420,22 @@ export class App { ? Math.round(filtered.reduce((s, h) => s + h.scores.current, 0) / filtered.length) : 0; - return Dom.div( - new DomOptions({ - children: [ - Dom.strong(`${filtered.length.toString()}/${houses.length}`), - Dom.span(" houses shown • Average score: "), - Dom.strong(averageScore.toString()), - Dom.span(" • Use weights sliders to adjust scoring"), - ], - id: "stats", - styles: { - background: "#fff", - borderTop: "1px solid #ddd", - flexShrink: "0", - fontSize: "0.95rem", - padding: "0.75rem 1rem", - }, - }), - ); + return Dom.div({ + children: [ + Dom.strong({ text: `${filtered.length.toString()}/${houses.length}` }), + Dom.span({ text: " houses shown • Average score: " }), + Dom.strong({ text: averageScore.toString() }), + Dom.span({ text: " • Use weights sliders to adjust scoring" }), + ], + id: "stats", + styles: { + background: "#fff", + borderTop: "1px solid #ddd", + flexShrink: "0", + fontSize: "0.95rem", + padding: "0.75rem 1rem", + }, + }); } } |
