@page "/prets" @using MaBibli.Shared.Textes @inject ServiceLivresApi Api @inject EtatReseau Reseau @implements IDisposable @* Ce qui n'est pas à la maison. C'est l'usage principal des prêts : savoir d'un coup d'œil quels livres sont dehors, et chez qui. La liste est commune à tout le foyer, sans filtre par utilisateur : n'importe qui doit pouvoir constater qu'un livre manque, et noter son retour quand il le récupère. *@ MaBibli — prêts en cours

Prêts en cours

@if (_erreur is not null) { } @if (_prets is null) {

Chargement…

} else if (_prets.Count == 0) { @* Hors-ligne, une liste vide peut aussi vouloir dire « rien n'a encore été enregistré ici » : on ne l'affirme comme un fait que si l'information vient bien d'une synchronisation. *@

@(Reseau.EnLigne || Reseau.DerniereSynchro is not null ? "Tous les livres sont à la maison." : "Aucune donnée enregistrée sur cet appareil : impossible de dire ce qui est prêté.")

} else {

@_prets.Count livre@(_prets.Count > 1 ? "s" : "") dehors

@* Filtre en mémoire : la liste des prêts en cours est courte, une forme normalisée en base serait disproportionnée pour ce seul besoin (voir CLAUDE.md, lot G). La recherche reste insensible aux accents et à la casse, comme partout ailleurs dans l'application. *@ @if (_prets.Count > 1) {
} @if (PretsAffiches().Count == 0) {

Aucun prêt ne correspond à « @_recherche ».

} } @code { private IReadOnlyList? _prets; private string? _erreur; private int? _enCours; private string _recherche = string.Empty; private void SurRecherche(ChangeEventArgs e) => _recherche = e.Value?.ToString() ?? string.Empty; private IReadOnlyList PretsAffiches() { if (_prets is null) { return []; } var terme = NormalisationTexte.Normaliser(_recherche); return terme.Length == 0 ? _prets : _prets.Where(p => NormalisationTexte.Normaliser(p.Emprunteur).Contains(terme)).ToList(); } protected override void OnInitialized() => Reseau.Change += SurChangementReseau; private void SurChangementReseau() => _ = InvokeAsync(async () => { await ChargerAsync(); StateHasChanged(); }); public void Dispose() => Reseau.Change -= SurChangementReseau; protected override Task OnInitializedAsync() => ChargerAsync(); private async Task ChargerAsync() { _erreur = null; try { _prets = await Api.ListerPretsEnCoursAsync(); } catch (Exception ex) { _erreur = $"Impossible de charger les prêts : {ex.Message}"; _prets = []; } } private async Task RendreAsync(PretDto pret) { _enCours = pret.Id; var resultat = await Api.RendreAsync(pret.Id); _enCours = null; if (!resultat.EstOk) { _erreur = resultat.Erreur; } // Rechargement complet plutôt que retrait local : quelqu'un d'autre du foyer a pu rendre // ou prêter un livre entre-temps, et cette vue est justement celle qu'on garde ouverte. await ChargerAsync(); } }