feat(ui): green map pin for applied flats, hide map reject after apply, lightbox image viewer
Map: replace Leaflet's default marker with a divIcon SVG pin coloured per state — green when the user has already successfully applied (status.chip === "ok"), brand-blue otherwise. Same condition also hides the action buttons in the popup, matching the list view, which already hid both Bewerben and Ablehnen on success — so the only remaining action on an applied flat is opening the original ad link. Image gallery: clicks now open a global lightbox modal instead of a new tab. The viewer fits each image into the viewport via max-width/height + object-fit: contain (uniform sizing regardless of source aspect), shows × top-right, prev/next arrows on the sides, ←/→/Esc keyboard nav, and click-on-backdrop to close. Prev arrow is hidden on the first image and next on the last. Tile changes from <a target="_blank"> to <button> since the new-tab fallback is no longer wanted. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fe43a402d8
commit
787f848aba
5 changed files with 173 additions and 21 deletions
|
|
@ -128,3 +128,76 @@ function openDeepLinkedFlat() {
|
|||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", openDeepLinkedFlat);
|
||||
|
||||
// Image lightbox — single global modal in base.html, opened by clicking any
|
||||
// .flat-gallery-tile. Click handler is delegated so it survives HTMX swaps.
|
||||
(function () {
|
||||
const overlay = document.getElementById("lazyflat-lightbox");
|
||||
if (!overlay) return;
|
||||
const imgEl = overlay.querySelector(".lightbox-image");
|
||||
const counterEl = overlay.querySelector(".lightbox-counter");
|
||||
const prevBtn = overlay.querySelector("[data-lightbox-prev]");
|
||||
const nextBtn = overlay.querySelector("[data-lightbox-next]");
|
||||
const closeBtn = overlay.querySelector("[data-lightbox-close]");
|
||||
let urls = [];
|
||||
let idx = 0;
|
||||
|
||||
function render() {
|
||||
imgEl.src = urls[idx];
|
||||
imgEl.alt = `Foto ${idx + 1} von ${urls.length}`;
|
||||
counterEl.textContent = urls.length > 1 ? `${idx + 1} / ${urls.length}` : "";
|
||||
prevBtn.hidden = idx <= 0;
|
||||
nextBtn.hidden = idx >= urls.length - 1;
|
||||
}
|
||||
|
||||
function open(list, startIdx) {
|
||||
if (!list.length) return;
|
||||
urls = list;
|
||||
idx = Math.max(0, Math.min(startIdx | 0, urls.length - 1));
|
||||
overlay.classList.remove("hidden");
|
||||
overlay.setAttribute("aria-hidden", "false");
|
||||
document.body.classList.add("lightbox-open");
|
||||
render();
|
||||
}
|
||||
|
||||
function close() {
|
||||
overlay.classList.add("hidden");
|
||||
overlay.setAttribute("aria-hidden", "true");
|
||||
document.body.classList.remove("lightbox-open");
|
||||
imgEl.removeAttribute("src");
|
||||
urls = [];
|
||||
}
|
||||
|
||||
function step(delta) {
|
||||
const next = idx + delta;
|
||||
if (next < 0 || next >= urls.length) return;
|
||||
idx = next;
|
||||
render();
|
||||
}
|
||||
|
||||
prevBtn.addEventListener("click", () => step(-1));
|
||||
nextBtn.addEventListener("click", () => step(1));
|
||||
closeBtn.addEventListener("click", close);
|
||||
overlay.addEventListener("click", (ev) => {
|
||||
if (ev.target === overlay) close();
|
||||
});
|
||||
document.addEventListener("keydown", (ev) => {
|
||||
if (overlay.classList.contains("hidden")) return;
|
||||
if (ev.key === "Escape") close();
|
||||
else if (ev.key === "ArrowLeft") step(-1);
|
||||
else if (ev.key === "ArrowRight") step(1);
|
||||
});
|
||||
|
||||
document.addEventListener("click", (ev) => {
|
||||
const tile = ev.target.closest(".flat-gallery-tile");
|
||||
if (!tile) return;
|
||||
const gallery = tile.closest(".flat-gallery");
|
||||
if (!gallery) return;
|
||||
ev.preventDefault();
|
||||
const tiles = Array.from(gallery.querySelectorAll(".flat-gallery-tile"));
|
||||
const list = tiles
|
||||
.map((t) => t.dataset.fullSrc || (t.querySelector("img") || {}).src || "")
|
||||
.filter(Boolean);
|
||||
open(list, tiles.indexOf(tile));
|
||||
});
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue