@page "/" @inject ServiceLivresApi Api @implements IDisposable MaBibli — catalogue

Catalogue

@if (_auteur is not null) { @* Le « cliquer sur un auteur » d'IDEES.md : le catalogue est ici restreint à ses livres. *@

Livres de @_auteur.Nom. Revenir à toute la bibliothèque

}
@foreach (var format in Enum.GetValues()) { }
@* Ce filtre porte sur MON statut, pas sur celui du foyer : un livre sans statut pour moi ne remonte sous aucune valeur, il reste visible sous « Tous ». *@
@foreach (var statut in Enum.GetValues()) { }
@if (_erreur is not null) { } @if (_chargement && _livres is null) {

Chargement…

} else if (_livres is { Count: 0 }) {

@(EstFiltre ? "Aucun livre ne correspond à cette recherche." : "La bibliothèque est vide. Ajoutez un premier livre.")

} else if (_livres is not null) {

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

} @code { /// Restreint le catalogue à un auteur. Vient de « ?auteur=… », posé par les liens de la liste. [SupplyParameterFromQuery(Name = "auteur")] public int? AuteurId { get; set; } private IReadOnlyList? _livres; private AuteurDto? _auteur; private int? _auteurCharge; private string _recherche = string.Empty; private Format? _format; private Statut? _statut; private bool _chargement; private string? _erreur; // Une frappe au clavier annule la recherche précédente encore en vol. private CancellationTokenSource _cts = new(); private bool EstFiltre => !string.IsNullOrWhiteSpace(_recherche) || _format is not null || _statut is not null || AuteurId is not null; protected override async Task OnParametersSetAsync() { if (_auteurCharge != AuteurId) { _auteurCharge = AuteurId; _auteur = AuteurId is { } id ? await Api.ObtenirAuteurAsync(id) : null; } await ChargerAsync(); } private async Task SurRecherche(ChangeEventArgs e) { _recherche = e.Value?.ToString() ?? string.Empty; await ChargerAsync(); } private Task FiltrerFormat(Format? format) { _format = format; return ChargerAsync(); } private Task FiltrerStatut(Statut? statut) { _statut = statut; return ChargerAsync(); } private async Task ChargerAsync() { _cts.Cancel(); _cts.Dispose(); _cts = new CancellationTokenSource(); var jeton = _cts.Token; _chargement = true; _erreur = null; try { var criteres = new CritereLivres { Recherche = _recherche, Format = _format, Statut = _statut, AuteurId = AuteurId, }; _livres = await Api.ListerAsync(criteres, jeton); } catch (OperationCanceledException) { return; // Une recherche plus récente a pris le relais. } catch (Exception ex) { _erreur = $"Impossible de charger le catalogue : {ex.Message}"; } finally { if (!jeton.IsCancellationRequested) { _chargement = false; } } } public void Dispose() { _cts.Cancel(); _cts.Dispose(); } }