diff options
| author | Petri Hienonen <petri.hienonen@gmail.com> | 2025-11-08 23:08:50 +0200 |
|---|---|---|
| committer | Petri Hienonen <petri.hienonen@gmail.com> | 2025-11-08 23:08:50 +0200 |
| commit | 644652342e4d57f2c3c9f70969596937823aa207 (patch) | |
| tree | 18708f1c49ad5f12ade61689d21470530e2baf8d /app/dom.js | |
| parent | 81cb28a961520dd8ff29af6aee67814804e07263 (diff) | |
| download | housing-644652342e4d57f2c3c9f70969596937823aa207.tar.zst | |
Modal
Diffstat (limited to '')
| -rw-r--r-- | app/dom.js | 269 |
1 files changed, 134 insertions, 135 deletions
@@ -217,139 +217,6 @@ export class Dom { export class Widgets { /** - * Build modal content for a house - * @param {House} house - * @returns {DocumentFragment} - */ - static buildModalContent(house) { - const frag = document.createDocumentFragment(); - - /* Header */ - const header = Dom.div( - new DomOptions({ - styles: { - alignItems: "center", - display: "flex", - justifyContent: "space-between", - marginBottom: "20px", - }, - }), - ); - - const title = Dom.heading( - 2, - house.address, - new DomOptions({ - styles: { color: "#333", fontSize: "20px", margin: "0" }, - }), - ); - const score = Dom.span( - `Score: ${house.scores.current.toFixed(1)}`, - new DomOptions({ - styles: { - background: "#e8f5e9", - borderRadius: "4px", - color: "#2e7d32", - fontSize: "16px", - fontWeight: "bold", - padding: "4px 8px", - }, - }), - ); - header.append(title, score); - frag.appendChild(header); - - const grid = Dom.div( - new DomOptions({ - styles: { - display: "grid", - gap: "15px", - gridTemplateColumns: "repeat(2,1fr)", - marginBottom: "20px", - }, - }), - ); - const details = [ - { label: "Price", value: `${house.price} €` }, - { label: "Building Type", value: house.buildingType }, - { label: "Construction Year", value: house.constructionYear?.toString() ?? "N/A" }, - { label: "Living Area", value: `${house.livingArea} m²` }, - { label: "District", value: house.district }, - { label: "Rooms", value: house.rooms?.toString() ?? "N/A" }, - { label: "Price", value: `${house.price} €` }, - { label: "Building Type", value: house.buildingType }, - { label: "Construction Year", value: house.constructionYear?.toString() ?? "N/A" }, - { label: "Living Area", value: `${house.livingArea} m²` }, - { label: "District", value: house.district }, - { label: "Rooms", value: house.rooms?.toString() ?? "N/A" }, - ]; - for (const { label, value } of details) { - const item = Dom.div( - new DomOptions({ - children: [ - Dom.span( - label, - new DomOptions({ - styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "4px" }, - }), - ), - Dom.span(value, new DomOptions({ styles: { color: "#333", fontSize: "14px" } })), - ], - }), - ); - grid.appendChild(item); - } - frag.appendChild(grid); - - /* Description */ - const descSect = Dom.div(new DomOptions({ styles: { marginBottom: "20px" } })); - const descTitle = Dom.span( - "Description", - new DomOptions({ - styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "5px" }, - }), - ); - const descText = Dom.p( - house.description ?? "No description available.", - new DomOptions({ - styles: { color: "#333", fontSize: "14px", lineHeight: "1.4", marginTop: "5px" }, - }), - ); - descSect.append(descTitle, descText); - frag.appendChild(descSect); - - /* Images */ - if (house.images?.length) { - const imgSect = Dom.div(new DomOptions({ styles: { marginBottom: "20px" } })); - const imgTitle = Dom.div( - new DomOptions({ - styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "10px" }, - }), - ); - const imgCont = Dom.div( - new DomOptions({ - styles: { display: "flex", gap: "10px", overflowX: "auto", paddingBottom: "5px" }, - }), - ); - for (const src of house.images.slice(0, 3)) { - imgCont.appendChild( - Dom.img( - src, - new DomOptions({ - attributes: { loading: "lazy" }, - styles: { borderRadius: "4px", flexShrink: "0", height: "100px" }, - }), - ), - ); - } - imgSect.append(imgTitle, imgCont); - frag.appendChild(imgSect); - } - - return frag; - } - - /** * Show toast notification * @param {string} message * @param {ToastType} [type=ToastType.error] @@ -521,6 +388,139 @@ export class Modal { #onClearMapTimer; /** + * Build modal content for a house + * @param {House} house + * @returns {DocumentFragment} + */ + static buildModalContent(house) { + const frag = document.createDocumentFragment(); + + /* Header */ + const header = Dom.div( + new DomOptions({ + styles: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + marginBottom: "20px", + }, + }), + ); + + const title = Dom.heading( + 2, + house.address, + new DomOptions({ + styles: { color: "#333", fontSize: "20px", margin: "0" }, + }), + ); + const score = Dom.span( + `Score: ${house.scores.current.toFixed(1)}`, + new DomOptions({ + styles: { + background: "#e8f5e9", + borderRadius: "4px", + color: "#2e7d32", + fontSize: "16px", + fontWeight: "bold", + padding: "4px 8px", + }, + }), + ); + header.append(title, score); + frag.appendChild(header); + + const grid = Dom.div( + new DomOptions({ + styles: { + display: "grid", + gap: "15px", + gridTemplateColumns: "repeat(2,1fr)", + marginBottom: "20px", + }, + }), + ); + const details = [ + { label: "Price", value: `${house.price} €` }, + { label: "Building Type", value: house.buildingType }, + { label: "Construction Year", value: house.constructionYear?.toString() ?? "N/A" }, + { label: "Living Area", value: `${house.livingArea} m²` }, + { label: "District", value: house.district }, + { label: "Rooms", value: house.rooms?.toString() ?? "N/A" }, + { label: "Price", value: `${house.price} €` }, + { label: "Building Type", value: house.buildingType }, + { label: "Construction Year", value: house.constructionYear?.toString() ?? "N/A" }, + { label: "Living Area", value: `${house.livingArea} m²` }, + { label: "District", value: house.district }, + { label: "Rooms", value: house.rooms?.toString() ?? "N/A" }, + ]; + for (const { label, value } of details) { + const item = Dom.div( + new DomOptions({ + children: [ + Dom.span( + label, + new DomOptions({ + styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "4px" }, + }), + ), + Dom.span(value, new DomOptions({ styles: { color: "#333", fontSize: "14px" } })), + ], + }), + ); + grid.appendChild(item); + } + frag.appendChild(grid); + + /* Description */ + const descSect = Dom.div(new DomOptions({ styles: { marginBottom: "20px" } })); + const descTitle = Dom.span( + "Description", + new DomOptions({ + styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "5px" }, + }), + ); + const descText = Dom.p( + house.description ?? "No description available.", + new DomOptions({ + styles: { color: "#333", fontSize: "14px", lineHeight: "1.4", marginTop: "5px" }, + }), + ); + descSect.append(descTitle, descText); + frag.appendChild(descSect); + + /* Images */ + if (house.images?.length) { + const imgSect = Dom.div(new DomOptions({ styles: { marginBottom: "20px" } })); + const imgTitle = Dom.div( + new DomOptions({ + styles: { fontSize: "14px", fontWeight: "bold", marginBottom: "10px" }, + }), + ); + const imgCont = Dom.div( + new DomOptions({ + styles: { display: "flex", gap: "10px", overflowX: "auto", paddingBottom: "5px" }, + }), + ); + for (const src of house.images.slice(0, 3)) { + imgCont.appendChild( + Dom.img( + src, + new DomOptions({ + attributes: { loading: "lazy" }, + styles: { borderRadius: "4px", flexShrink: "0", height: "100px" }, + }), + ), + ); + } + imgSect.append(imgTitle, imgCont); + frag.appendChild(imgSect); + } + + return frag; + } + + /** * @param {House} house * @param {boolean} persistent * @param {object} positionStyles @@ -572,8 +572,7 @@ export class Modal { }), ); - this.#dialog.appendChild(closeBtn); - this.#dialog.appendChild(Widgets.buildModalContent(house)); + this.#dialog.append(closeBtn, Modal.buildModalContent(house)); // Add event listeners with AbortController this.#dialog.addEventListener("close", () => this.hide(), { |
