|
|
|
|
@@ -357,6 +357,73 @@
|
|
|
|
|
.extra-kv-item .ek { color: var(--text-dimmer); }
|
|
|
|
|
.extra-kv-item .ev { color: var(--text); margin-left: 0.3rem; }
|
|
|
|
|
|
|
|
|
|
/* ── Energielabel badge ── */
|
|
|
|
|
.el-badge {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
font-size: 0.62rem;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
font-family: var(--font-mono);
|
|
|
|
|
padding: 0.1rem 0.35rem;
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
letter-spacing: 0.03em;
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
color: #fff;
|
|
|
|
|
min-width: 1.8rem;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
.el-Appp { background: #004f2d; }
|
|
|
|
|
.el-App { background: #006837; }
|
|
|
|
|
.el-Ap { background: #1a9641; }
|
|
|
|
|
.el-A { background: #3cb54a; }
|
|
|
|
|
.el-B { background: #69b444; }
|
|
|
|
|
.el-C { background: #a6d854; color: #2e2a25; }
|
|
|
|
|
.el-D { background: #f9c819; color: #2e2a25; }
|
|
|
|
|
.el-E { background: #f4a432; color: #2e2a25; }
|
|
|
|
|
.el-F { background: #e8612d; }
|
|
|
|
|
.el-G { background: #c0392b; }
|
|
|
|
|
.el-unknown { background: var(--surface2); color: var(--text-dim); border: 1px solid var(--border); }
|
|
|
|
|
|
|
|
|
|
/* ── Search bar ── */
|
|
|
|
|
#f-search {
|
|
|
|
|
background: var(--surface);
|
|
|
|
|
border: 1px solid var(--border);
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
color: var(--text);
|
|
|
|
|
font-family: var(--font-ui);
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
padding: 0.3rem 0.6rem;
|
|
|
|
|
outline: none;
|
|
|
|
|
width: 11rem;
|
|
|
|
|
transition: border-color 0.15s;
|
|
|
|
|
}
|
|
|
|
|
#f-search::placeholder { color: var(--text-dimmer); }
|
|
|
|
|
#f-search:focus { border-color: var(--accent); }
|
|
|
|
|
|
|
|
|
|
/* ── Disable filters toggle ── */
|
|
|
|
|
#filter-disable {
|
|
|
|
|
background: none;
|
|
|
|
|
border: 1px solid var(--border);
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
color: var(--text-dimmer);
|
|
|
|
|
font-family: var(--font-ui);
|
|
|
|
|
font-size: 0.7rem;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
letter-spacing: 0.04em;
|
|
|
|
|
text-transform: uppercase;
|
|
|
|
|
padding: 0.3rem 0.7rem;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: color 0.15s, border-color 0.15s, background 0.15s;
|
|
|
|
|
}
|
|
|
|
|
#filter-disable:hover { color: var(--text); border-color: var(--text-dim); }
|
|
|
|
|
#filter-disable.active {
|
|
|
|
|
background: var(--orange);
|
|
|
|
|
border-color: var(--orange);
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ── No results ── */
|
|
|
|
|
#empty { display: none; }
|
|
|
|
|
#empty.visible { display: block; }
|
|
|
|
|
@@ -407,6 +474,8 @@
|
|
|
|
|
<option value="opp_desc">Opp. ↓</option>
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
<input type="search" id="f-search" placeholder="Zoek adres, stad…">
|
|
|
|
|
<button id="filter-disable">Filters uit</button>
|
|
|
|
|
<button id="filter-reset">Reset</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
@@ -464,6 +533,14 @@ function fmt_extra_val(v) {
|
|
|
|
|
return s.length > 120 ? s.slice(0, 120) + '…' : s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function el_class(label) {
|
|
|
|
|
if (!label) return 'el-unknown';
|
|
|
|
|
const s = label.replace(/\+/g, 'p').replace(/-/g, '');
|
|
|
|
|
const map = { 'Appp': 'el-Appp', 'App': 'el-App', 'Ap': 'el-Ap', 'A': 'el-A',
|
|
|
|
|
'B': 'el-B', 'C': 'el-C', 'D': 'el-D', 'E': 'el-E', 'F': 'el-F', 'G': 'el-G' };
|
|
|
|
|
return map[s] || 'el-unknown';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ef(label, val) {
|
|
|
|
|
if (val == null || val === '' || val === 'null') return '';
|
|
|
|
|
return `<div class="expanded-field">
|
|
|
|
|
@@ -529,7 +606,7 @@ function render_card(l) {
|
|
|
|
|
</div>
|
|
|
|
|
${l.woonoppervlak ? `<div class="card-meta-item"><span class="icon">📐</span><span class="val">${l.woonoppervlak} m²</span></div>` : ''}
|
|
|
|
|
${l.kamers ? `<div class="card-meta-item"><span class="icon">🚪</span><span class="val">${l.kamers} kamers</span></div>` : ''}
|
|
|
|
|
${l.energielabel ? `<div class="card-meta-item"><span class="icon">🔋</span><span class="val">${l.energielabel} energielabel</span></div>` : ''}
|
|
|
|
|
${l.energielabel ? `<div class="card-meta-item"><span class="el-badge ${el_class(l.energielabel)}">${l.energielabel}</span></div>` : ''}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-toggle">meer ↓</div>
|
|
|
|
|
</div>
|
|
|
|
|
@@ -558,6 +635,8 @@ function render_card(l) {
|
|
|
|
|
|
|
|
|
|
// ── Filter + sort + render ──
|
|
|
|
|
|
|
|
|
|
let filters_disabled = false;
|
|
|
|
|
|
|
|
|
|
function get_filters() {
|
|
|
|
|
return {
|
|
|
|
|
ov_mark: parseInt(document.getElementById('f-ov-mark').value) || Infinity,
|
|
|
|
|
@@ -566,6 +645,7 @@ function get_filters() {
|
|
|
|
|
prijs: parseInt(document.getElementById('f-prijs').value) || Infinity,
|
|
|
|
|
opp: parseInt(document.getElementById('f-opp').value) || 0,
|
|
|
|
|
sort: document.getElementById('f-sort').value,
|
|
|
|
|
search: document.getElementById('f-search').value.trim().toLowerCase(),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -583,11 +663,18 @@ const SORT_FNS = {
|
|
|
|
|
function apply() {
|
|
|
|
|
const f = get_filters();
|
|
|
|
|
let filtered = LISTINGS.filter(l => {
|
|
|
|
|
if (!filters_disabled) {
|
|
|
|
|
if (f.ov_mark < Infinity && (l.ov_mark == null || l.ov_mark > f.ov_mark)) return false;
|
|
|
|
|
if (f.ov_michelle < Infinity && (l.ov_michelle == null || l.ov_michelle > f.ov_michelle)) return false;
|
|
|
|
|
if (f.fiets_mark < Infinity && (l.fiets_mark == null || l.fiets_mark > f.fiets_mark)) return false;
|
|
|
|
|
if (l.prijs != null && l.prijs > f.prijs) return false;
|
|
|
|
|
if (f.opp > 0 && (l.woonoppervlak == null || l.woonoppervlak < f.opp)) return false;
|
|
|
|
|
}
|
|
|
|
|
if (f.search) {
|
|
|
|
|
const haystack = [l.adres, l.stad, l.postcode, l.source_makelaar, l.woningtype]
|
|
|
|
|
.filter(Boolean).join(' ').toLowerCase();
|
|
|
|
|
if (!haystack.includes(f.search)) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -630,10 +717,21 @@ document.querySelectorAll('#filters input, #filters select').forEach(el => {
|
|
|
|
|
el.addEventListener('input', apply);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.getElementById('filter-disable').addEventListener('click', () => {
|
|
|
|
|
filters_disabled = !filters_disabled;
|
|
|
|
|
document.getElementById('filter-disable').classList.toggle('active', filters_disabled);
|
|
|
|
|
document.getElementById('filter-disable').textContent = filters_disabled ? 'Filters aan' : 'Filters uit';
|
|
|
|
|
apply();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.getElementById('filter-reset').addEventListener('click', () => {
|
|
|
|
|
Object.entries(DEFAULTS).forEach(([id, val]) => {
|
|
|
|
|
document.getElementById(id).value = val;
|
|
|
|
|
});
|
|
|
|
|
document.getElementById('f-search').value = '';
|
|
|
|
|
filters_disabled = false;
|
|
|
|
|
document.getElementById('filter-disable').classList.remove('active');
|
|
|
|
|
document.getElementById('filter-disable').textContent = 'Filters uit';
|
|
|
|
|
apply();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|