@using MaBibli.Client.Services @* Un bloc de série au catalogue, replié ou déplié — et récursif, parce qu'un cycle est une série de séries : chaque niveau porte sa propre bascule. ⚠️ Tout est REPLIÉ par défaut ici (2026-09-10), à l'inverse de l'arbre des séries : le catalogue liste D'ABORD les livres, une série n'y est qu'un détail qu'on ouvre au besoin — alors que l'écran des séries EST la liste des séries, où les masquer toutes viderait l'écran. ⚠️ Replié, le bloc annonce toujours ce qu'il contient : sans ce compte, le compteur du haut du catalogue paraîtrait mentir. ⚠️ Et ce compte distingue trois choses (2026-09-08) : ce qui est AFFICHÉ (filtre compris), ce qu'on POSSÈDE de cette série, et ce qu'elle compte de tomes. Un seul nombre suivait le filtre — « 3 tomes » devenait « 1 tome » sous une recherche, et se lisait « cette série n'a qu'un tome ». Les égalités se replient : sans filtre et série complète, on relit « 3 tomes ». *@
  • @* ⚠️ Aria.Etat, et non le booléen nu : voir la mise en garde qu'il porte. *@ @* Le nom mène à la SÉRIE : c'est le seul écran qui montre aussi les tomes manquants, ce que le catalogue ne peut pas faire. *@ @Entree.Serie!.Titre @Libelles.CompteBloc(Entree.NombreLivres, Possedes, Total)
    @if (Deplie) { @if (Entree.SousEntrees.Count > 0) { } @if (Entree.Livres.Count > 0) { } }
  • @code { [Parameter, EditorRequired] public EntreeCatalogue Entree { get; set; } = default!; /// /// Blocs OUVERTS, par identifiant de série — et non repliés : le défaut est de tout replier. /// /// /// État local de l'écran, volontairement non persistant : c'est un confort de lecture, pas /// une propriété de la série. Il survit en revanche aux rechargements du catalogue (frappe /// dans la recherche, filtre), le jeu appartenant à l'écran et non au bloc. /// [Parameter, EditorRequired] public ISet Ouverts { get; set; } = new HashSet(); /// /// Compteurs par série, descendance comprise : ce qu'on possède, et ce que la série recense. /// /// /// ⚠️ Calculés une fois par l'écran (TotauxSeries), et non ici : le catalogue se relit /// à chaque frappe dans la recherche, et chaque bloc les recalculerait pour tout l'arbre. /// C'est aussi ce qui garantit le même compte que la fiche de la série. /// [Parameter] public IReadOnlyDictionary? Totaux { get; set; } /// Modification en lot du catalogue : voir la remarque équivalente sur Catalogue.razor. [Parameter] public bool LotActif { get; set; } [Parameter] public ISet? SelectionLot { get; set; } /// /// ⚠️ EventCallback, et non un Action brut : coché depuis un tome niché dans ce bloc, l'écran /// du catalogue (le VRAI propriétaire de la sélection) ne serait sinon jamais prévenu du /// changement, et sa barre de sélection resterait figée sur l'état d'avant — le second piège /// Blazor de CLAUDE.md. /// [Parameter] public EventCallback<(int LivreId, bool Coche)> OnSelectionner { get; set; } private (int Possedes, int Total) Compte => Totaux is not null && Totaux.TryGetValue(Entree.Serie!.Id, out var connu) ? connu : (Entree.NombreLivres, Entree.NombreLivres); private int Possedes => Compte.Possedes; private int Total => Compte.Total; private bool Deplie => Ouverts.Contains(Entree.Serie!.Id); private void Basculer() { if (!Ouverts.Add(Entree.Serie!.Id)) { Ouverts.Remove(Entree.Serie!.Id); } } }