namespace MaBibli.Shared.Dtos; /// /// Une série telle qu'exposée par l'API — trilogie, cycle, intégrale. /// /// /// La liste est rendue à plat, chaque série portant l'identifiant de sa parente, et c'est /// le client qui rebâtit l'arbre. Deux raisons : un JSON récursif se cache mal dans un /// instantané hors-ligne, et une seule lecture suffit alors à servir la liste et le /// détail — donc un seul instantané à tenir à jour. /// public record SerieDto { public required int Id { get; init; } public required string Titre { get; init; } /// La série qui contient celle-ci, si elle fait partie d'un cycle. public int? SerieParenteId { get; init; } /// Rang dans la série parente. Sans objet à la racine. public int Position { get; init; } /// Les tomes, dans l'ordre de lecture. public IReadOnlyList Elements { get; init; } = []; /// Qui a créé la série. Trace d'affichage : la série est commune au foyer. public string? AjoutePar { get; init; } /// Tomes possédés sur tomes recensés — « 4 sur 7 », le cœur de l'écran. public int NombrePossedes => Elements.Count(e => e.Possede); } /// /// Une place dans l'ordre de lecture, occupée ou non. /// /// /// ⚠️ Un élément sans n'est pas une anomalie : c'est un tome qu'on /// ne possède pas, et c'est précisément ce que l'écran doit montrer. /// public record ElementSerieDto { public required int Id { get; init; } public int Position { get; init; } /// Titre du tome : celui du livre quand il est rattaché, sinon celui qui a été saisi. public required string Titre { get; init; } public int? LivreId { get; init; } public bool Possede => LivreId is not null; /// Auteurs du livre rattaché, pour ne pas avoir à ouvrir sa fiche. public string? Auteurs { get; init; } /// À qui le tome est prêté, s'il est dehors. Commun au foyer, comme tout prêt. public string? PreteA { get; init; } } /// Charge utile de création ou de renommage d'une série. public record EnregistrementSerie { public string Titre { get; set; } = string.Empty; /// Série parente, pour ranger une trilogie dans un cycle. null = à la racine. public int? SerieParenteId { get; set; } } /// /// Charge utile d'ajout d'un tome : soit un livre du catalogue, soit un simple titre. /// /// /// Les deux voies existent parce qu'une saga se recense d'un coup — souvent avant d'en posséder /// la moitié — puis se remplit au fil des achats. /// public record AjoutElementSerie { /// Livre du catalogue à placer ici. null = un tome qu'on ne possède pas. public int? LivreId { get; set; } /// Titre du tome. Obligatoire sans livre ; repris du livre sinon. public string? Titre { get; set; } } /// Nouvel ordre de lecture : la liste entière des identifiants d'éléments. /// /// Comme pour la liste d'envies, on prend la liste complète plutôt qu'un déplacement unitaire : /// une seule opération à vérifier, et c'est ce dont a besoin le glisser-déposer comme les /// flèches. /// public record OrdreElementsSerie { public List Ids { get; set; } = []; } /// Nouvel ordre des séries directement contenues dans un cycle. public record OrdreSeries { public List Ids { get; set; } = []; } /// Déplacement d'une série dans l'ordre de lecture de son cycle. public readonly record struct DeplacementSerie(int SerieId, int ParenteId, int Delta);