map view (Leaflet + OSM), iOS switches, Alarm → Benachrichtigungen
* flats: new lat/lng columns (migration v3); alert geocodes every new flat through googlemaps and ships coords in the payload * web: CSP extended for unpkg (leaflet.css) + tile.openstreetmap.org * Wohnungen tab: Liste/Karte view toggle (segmented, CSS-only via :has(), selection persisted in localStorage). Karte shows passende flats as Pins on an OSM tile map; Popup per Pin mit Adresse, Zimmer/m²/€ und Link * Top-strip toggles are now proper iOS-style toggle switches (single rounded knob sliding in a pill, red when on), no descriptive subtitle * Alarm-Karte verlinkt jetzt auf /einstellungen/benachrichtigungen (Filter-Karte bleibt /einstellungen/filter) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d9468f6814
commit
376551213a
8 changed files with 239 additions and 83 deletions
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<!-- Reihe 1: Info-Kacheln Alarm + Filter -->
|
||||
<section class="grid grid-cols-2 gap-3">
|
||||
<a class="card px-4 py-2.5 flex flex-col gap-0.5 hover:bg-[#f6fafd]" href="/einstellungen/filter">
|
||||
<a class="card px-4 py-2.5 flex flex-col gap-0.5 hover:bg-[#f6fafd]" href="/einstellungen/benachrichtigungen">
|
||||
<div class="text-[11px] uppercase tracking-wide text-slate-500">Alarm</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="chip chip-{{ alert_chip }}">{{ alert_label }}</span>
|
||||
|
|
@ -21,68 +21,36 @@
|
|||
|
||||
<!-- Reihe 2: Schalter Automatisch bewerben + Final absenden -->
|
||||
<section class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
<!-- Automatisch bewerben -->
|
||||
<form class="card p-4 flex items-center justify-between gap-3">
|
||||
<input type="hidden" name="csrf" value="{{ csrf }}">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<div class="text-[11px] uppercase tracking-wide text-slate-500">Automatisch bewerben</div>
|
||||
<div class="text-xs text-slate-500">bei Match ohne Nachfrage bewerben</div>
|
||||
</div>
|
||||
<div class="toggle warn">
|
||||
<label>
|
||||
<input type="radio" name="value" value="off"
|
||||
hx-post="/actions/auto-apply"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
{% if not auto_apply_enabled %}checked{% endif %}>
|
||||
Aus
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="value" value="on"
|
||||
hx-post="/actions/auto-apply"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Automatisches Bewerben einschalten? Bei jedem passenden Flat wird automatisch beworben."
|
||||
{% if auto_apply_enabled %}checked{% endif %}>
|
||||
An
|
||||
</label>
|
||||
</div>
|
||||
<div class="text-sm font-medium">Automatisch bewerben</div>
|
||||
<label class="switch warn">
|
||||
<input type="checkbox" name="value" value="on"
|
||||
hx-post="/actions/auto-apply"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
{% if not auto_apply_enabled %}hx-confirm="Automatisches Bewerben einschalten? Bei jedem passenden Flat wird automatisch beworben."{% endif %}
|
||||
{% if auto_apply_enabled %}checked{% endif %}>
|
||||
<span class="switch-visual"></span>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<!-- Final absenden (inverse of submit_forms: on=real, off=trocken) -->
|
||||
<form class="card p-4 flex items-center justify-between gap-3">
|
||||
<input type="hidden" name="csrf" value="{{ csrf }}">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<div class="text-[11px] uppercase tracking-wide text-slate-500">Final absenden</div>
|
||||
<div class="text-xs text-slate-500">aus = Formular ausfüllen, nicht abschicken</div>
|
||||
</div>
|
||||
<div class="toggle warn">
|
||||
<label>
|
||||
<input type="radio" name="value" value="off"
|
||||
hx-post="/actions/submit-forms"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
{% if not submit_forms %}checked{% endif %}>
|
||||
Aus
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="value" value="on"
|
||||
hx-post="/actions/submit-forms"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
hx-confirm="Final absenden einschalten? Formulare werden dann WIRKLICH abgeschickt!"
|
||||
{% if submit_forms %}checked{% endif %}>
|
||||
An
|
||||
</label>
|
||||
</div>
|
||||
<div class="text-sm font-medium">Final absenden</div>
|
||||
<label class="switch warn">
|
||||
<input type="checkbox" name="value" value="on"
|
||||
hx-post="/actions/submit-forms"
|
||||
hx-trigger="change"
|
||||
hx-include="closest form"
|
||||
hx-target="#wohnungen-body"
|
||||
hx-swap="outerHTML"
|
||||
{% if not submit_forms %}hx-confirm="Final absenden einschalten? Formulare werden dann WIRKLICH abgeschickt!"{% endif %}
|
||||
{% if submit_forms %}checked{% endif %}>
|
||||
<span class="switch-visual"></span>
|
||||
</label>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
|
|
@ -107,17 +75,42 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Liste passender Wohnungen -->
|
||||
<section class="card">
|
||||
<div class="flex items-center justify-between px-4 py-3 border-b border-soft gap-4 flex-wrap">
|
||||
<h2 class="font-semibold">Passende Wohnungen auf inberlinwohnen.de</h2>
|
||||
<div class="text-xs text-slate-500 flex gap-3 items-center">
|
||||
<span>{{ flats|length }} gefunden</span>
|
||||
{% if next_scrape_utc %}
|
||||
<span>· nächste Aktualisierung <span data-countdown-utc="{{ next_scrape_utc }}">…</span></span>
|
||||
{% endif %}
|
||||
<!-- Header + View-Toggle (Liste/Karte) -->
|
||||
<section class="flex items-center justify-between gap-4 flex-wrap">
|
||||
<h2 class="font-semibold">Passende Wohnungen auf inberlinwohnen.de</h2>
|
||||
<div class="flex items-center gap-3 text-xs text-slate-500">
|
||||
<span>{{ flats|length }} gefunden</span>
|
||||
{% if next_scrape_utc %}
|
||||
<span>· nächste Aktualisierung <span data-countdown-utc="{{ next_scrape_utc }}">…</span></span>
|
||||
{% endif %}
|
||||
<div class="view-toggle ml-2">
|
||||
<label>
|
||||
<input type="radio" name="view_mode" id="v_list" value="list" checked>
|
||||
Liste
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="view_mode" id="v_map" value="map">
|
||||
Karte
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Karte -->
|
||||
<section class="view-map">
|
||||
<div class="card p-3">
|
||||
<div id="flats-map" data-flats='{{ map_points | tojson }}'></div>
|
||||
{% if not map_points %}
|
||||
<p class="mt-3 text-xs text-slate-500">
|
||||
Keine Koordinaten für passende Wohnungen vorhanden —
|
||||
entweder sind noch keine neuen Flats geocoded worden oder die Filter lassen noch nichts durch.
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Liste -->
|
||||
<section class="view-list card">
|
||||
<div class="divide-y divide-soft">
|
||||
{% for item in flats %}
|
||||
{% set f = item.row %}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue