---
name: project_leases_ajax_refresh
description: Actualisation AJAX de la page Leases (conserve filtres/tri/mode, auto-refresh 60s, feedback visuel)
metadata:
  type: project
---

Le bouton **Actualiser** de la page Leases (et l'auto-refresh) ne recharge plus la page :
re-fetch AJAX + re-render en place → **filtres (recherche/subnet/état), tri, mode groupé/plat
et repli sont conservés** (ré-appliqués par `render()`). Résout la perte des filtres au reload.

- `LeaseService::getEnrichedLeases()` : **factorisation** de la construction du tableau enrichi
  (leases Kea × subnets × réservations, 11 clés dont host_id/group_name). Source unique partagée
  entre le rendu initial de `leases.php` et l'endpoint AJAX. Vérifiée E2E contre le vrai Kea.
- `public/leases_data.php` : endpoint JSON (requireLogin) → `echo json_encode(getEnrichedLeases())`.
- `leases.php` JS : `ALL_LEASES` passé en `let` (réassigné au fetch) ; `fetch('leases_data.php')`
  → réassigne + `render()`. Échec réseau silencieux (garde les données courantes).
- **Auto-refresh porté de 30s → 60s** avec re-fetch réel des leases (avant : juste recalcul local
  du temps restant). `setInterval(refreshLeases(false), 60000)`.
- **Feedback visuel manuel** : spin d'icône garanti ~500ms (`.spin`) + halo bleu pulsant sur les
  4 cartes de stats en haut (`#stats-row.stats-flash`, box-shadow → identique clair/sombre).
  L'auto-refresh ne déclenche que le spin (pas de flash parasite chaque minute).

**Piège récurrent de la page Leases** : rendu 100% JS via innerHTML reconstruit à chaque
`render()` → tout état d'UI doit vivre hors DOM (variables/Set/localStorage). Cf.
[[project_leases_grouping]]. API Kea réelle : voir [[project_lease_release]].
