@page "/series"
@inject ServiceLivresApi Api
@inject EtatReseau Reseau
@implements IDisposable
MaBibli — séries
Séries
Sagas, cycles et trilogies, dans leur ordre de lecture — qui n'est pas
toujours celui de publication. Les séries sont communes au foyer, comme le catalogue.
@if (_erreur is not null)
{
@_erreur
}
@* Créer une série depuis la liste : c'est le seul endroit d'où l'on part, et un écran de plus
pour un unique champ ne se justifierait pas. *@
Créer la série
@if (_series is null)
{
Chargement…
}
else if (_series.Count == 0)
{
Aucune série pour l'instant. Créez-en une, puis ajoutez-y vos livres et les tomes
qui vous manquent : c'est ce qui permet de voir les trous.
}
else
{
@foreach (var serie in Racines)
{
@serie.Titre
@Avancement(serie)
@* Un cycle contient des séries : elles se voient d'ici, sans ouvrir le cycle. *@
@if (Filles(serie.Id) is { Count: > 0 } filles)
{
@foreach (var fille in filles)
{
@fille.Titre
@Avancement(fille)
}
}
}
}
@code {
private IReadOnlyList? _series;
private string _nouveau = string.Empty;
private bool _enCours;
private string? _erreur;
private string? MotifBlocage => Reseau.EnLigne ? null : EtatReseau.MotifHorsLigne;
/// Séries de premier niveau. Celles rangées dans un cycle s'affichent sous lui.
private IEnumerable Racines =>
_series?.Where(s => s.SerieParenteId is null) ?? [];
private List Filles(int parenteId) =>
_series?.Where(s => s.SerieParenteId == parenteId).OrderBy(s => s.Position).ToList() ?? [];
///
/// « 4 tomes sur 7 » : le compteur est l'information principale de l'écran.
///
///
/// Une série sans aucun tome ne se décrit pas par « 0 sur 0 », qui ressemble à une erreur :
/// elle dit ce qu'il faut faire.
///
private static string Avancement(SerieDto serie) =>
serie.Elements.Count == 0
? "Aucun tome recensé"
: $"{serie.NombrePossedes} tome{(serie.NombrePossedes > 1 ? "s" : "")} sur {serie.Elements.Count}";
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() => _series = await Api.ListerSeriesAsync();
private async Task SurTouche(KeyboardEventArgs e)
{
if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(_nouveau) && Reseau.EnLigne)
{
await CreerAsync();
}
}
private async Task CreerAsync()
{
_enCours = true;
_erreur = null;
var resultat = await Api.CreerSerieAsync(new EnregistrementSerie { Titre = _nouveau });
_enCours = false;
if (!resultat.EstOk)
{
_erreur = resultat.Erreur;
return;
}
_nouveau = string.Empty;
await ChargerAsync();
}
}