Ajouter les sagas et cycles, avec leurs tomes manquants
Première relation entre livres du projet. Une série contient des séries (un cycle EST une série de séries) et des PLACES dans l'ordre de lecture — pas des livres : une place sans livre est le trou qu'on vient voir. L'ordre est stocké, jamais déduit d'une année : une préquelle se lit avant le livre paru dix ans plus tôt. Les tomes non possédés se saisissent à la main, aucune source ne donnant l'ordre de lecture d'une saga. Le titre de la place survit à la suppression du livre (SetNull, pas de cascade), sans quoi perdre un exemplaire effacerait le tome 3 de la série. Les séries sont communes au foyer. Seule exception : la mise en envies d'un tome manquant, qui écrit dans une liste personnelle — c'est le seul point où les deux portées se rencontrent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -109,6 +109,19 @@ else
|
||||
</p>
|
||||
}
|
||||
|
||||
@*
|
||||
Les séries auxquelles ce livre appartient. Il peut y en avoir plusieurs — une
|
||||
trilogie, une intégrale, un cycle — d'où une liste et non un champ.
|
||||
⚠️ Lu depuis l'instantané des séries, donc disponible hors-ligne comme le reste.
|
||||
*@
|
||||
@foreach (var appartenance in _appartenances)
|
||||
{
|
||||
<p class="fiche-serie">
|
||||
Tome @appartenance.Rang de
|
||||
<a href="@($"series/{appartenance.Serie.Id}")">@appartenance.Serie.Titre</a>
|
||||
</p>
|
||||
}
|
||||
|
||||
<dl class="fiche-champs">
|
||||
@if (!string.IsNullOrWhiteSpace(_livre.Editeur))
|
||||
{
|
||||
@@ -180,6 +193,35 @@ else
|
||||
[Parameter] public int Id { get; set; }
|
||||
|
||||
private LivreDto? _livre;
|
||||
|
||||
/// <summary>Places de ce livre dans des séries : la série, et son rang de lecture.</summary>
|
||||
private IReadOnlyList<AppartenanceSerie> _appartenances = [];
|
||||
|
||||
private sealed record AppartenanceSerie(SerieDto Serie, int Rang);
|
||||
|
||||
/// <summary>
|
||||
/// Cherche ce livre dans les séries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Une seule lecture rend tout l'arbre, et elle est déjà en cache : chercher côté client
|
||||
/// évite un point d'entrée « séries d'un livre » qui n'aurait servi qu'ici, et qui aurait
|
||||
/// eu son propre instantané à tenir.
|
||||
/// <para>
|
||||
/// Le rang affiché est la <b>position dans l'ordre de lecture</b>, à partir de 1 — pas un
|
||||
/// numéro de tome imprimé sur la couverture, que le modèle ne connaît pas.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private async Task ChargerAppartenancesAsync()
|
||||
{
|
||||
var series = await Api.ListerSeriesAsync();
|
||||
|
||||
_appartenances = series
|
||||
.SelectMany(serie => serie.Elements
|
||||
.Select((element, index) => (serie, element, index))
|
||||
.Where(x => x.element.LivreId == Id)
|
||||
.Select(x => new AppartenanceSerie(x.serie, x.index + 1)))
|
||||
.ToList();
|
||||
}
|
||||
private EnregistrementLivre? _saisie;
|
||||
private bool _introuvable;
|
||||
private bool _enregistrement;
|
||||
@@ -252,6 +294,7 @@ else
|
||||
try
|
||||
{
|
||||
_livre = await Api.ObtenirAsync(Id);
|
||||
await ChargerAppartenancesAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user