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:
Moritz 2026-04-21 12:02:40 +02:00
parent d9468f6814
commit 376551213a
8 changed files with 239 additions and 83 deletions

View file

@ -132,8 +132,9 @@ async def security_headers(request: Request, call_next):
"Content-Security-Policy",
"default-src 'self'; "
"script-src 'self' https://cdn.tailwindcss.com https://unpkg.com; "
"style-src 'self' https://cdn.tailwindcss.com 'unsafe-inline'; "
"img-src 'self' data:; connect-src 'self'; frame-ancestors 'none';"
"style-src 'self' https://cdn.tailwindcss.com https://unpkg.com 'unsafe-inline'; "
"img-src 'self' data: https://*.tile.openstreetmap.org https://tile.openstreetmap.org; "
"connect-src 'self'; frame-ancestors 'none';"
)
return resp
@ -394,8 +395,22 @@ def _wohnungen_context(user) -> dict:
allowed, reason = _manual_apply_allowed()
alert_label, alert_chip = _alert_status(filters_row, notif_row)
has_running = _has_running_application(uid)
map_points = []
for item in flats_view:
f = item["row"]
if f["lat"] is None or f["lng"] is None:
continue
map_points.append({
"lat": f["lat"], "lng": f["lng"],
"address": f["address"] or f["link"],
"link": f["link"],
"rent": f["total_rent"],
"rooms": f["rooms"],
"size": f["size"],
})
return {
"flats": flats_view,
"map_points": map_points,
"alert_label": alert_label,
"alert_chip": alert_chip,
"filter_summary": _filter_summary(filters_row),
@ -462,7 +477,7 @@ async def action_save_filters(
@app.post("/actions/auto-apply")
async def action_auto_apply(
request: Request,
value: str = Form(...),
value: str = Form(default="off"),
csrf: str = Form(...),
user=Depends(require_user),
):
@ -834,7 +849,7 @@ async def action_password(
@app.post("/actions/submit-forms")
async def action_submit_forms(
request: Request,
value: str = Form(...),
value: str = Form(default="off"),
csrf: str = Form(...),
user=Depends(require_user),
):