Files
mabibli/MaBibli.Shared/Dtos/SerieDto.cs
T
mathieu 42dec0dbd1 - Catalogage rapide (douchette, code-barres)
- Cataloguer en rafale — nouvel écran /ajout/rafale : on scanne une pile de livres à la suite dans une zone de texte, chaque code est traité (BnF puis OpenLibrary), les doublons connus sont passés automatiquement. La collecte marche même hors-ligne. Le compte rendu liste maintenant les livres créés, en lien vers leur fiche, et reste consultable en revenant sur l'écran même après une rafale entièrement réussie. Le catalogue reconnaît un ISBN dans sa barre de recherche (13 ou 10 chiffres, avec ou sans tirets) : scanner un livre en main ouvre directement sa fiche s'il n'y en a qu'un. Un bouton « Scanner » l'alimente, actif hors-ligne.
- Ajouter un tome à une série accepte aussi un ISBN dans le champ manuel : le catalogue est cherché d'abord (rattachement direct si un seul exemplaire), sinon la BnF prend le relais.
Séries et sagas
- Numéro de tome distinct de la position de lecture : on peut indiquer « c'est le tome 7 » même si on ne possède pas les six premiers ; l'ordre de lecture reste un réglage séparé (utile pour les préquelles).
- Tri par numéro en plus du tri par ordre de lecture quand des tomes en portent un.
- Panneau « Ajouter » regroupé et repliable sur la fiche d'une série (manuellement / en rafale / depuis le catalogue / depuis les envies), au lieu de quatre formulaires ouverts en permanence.
- Filtre catalogue « sans couverture » pour repérer les livres à illustrer.
Le catalogue groupe les tomes d'une même série sous un bloc repliable, avec un décompte plus clair (affichés / possédés / total).
- Corrections directes sur la fiche
- Effacer un prêt saisi par erreur (bouton ✕ sur chaque ligne, avec confirmation), sans passer par « rendre ».
- Corriger une couverture manquante ou cassée en cliquant dessus : le champ d'adresse s'ouvre focalisé, Entrée enregistre. Étendu aux numéros de revue dans la dernière modification.
- Les thèmes déjà utilisés dans la bibliothèque sont proposés à la frappe.
- La recherche d'un livre à rattacher montre des suggestions dès le focus, sans attendre de taper.

- Visuel : un rendu manquant après une écriture asynchrone dans le formulaire de livre, une bascule de rôle cassée, des débordements à 320 px, et le style d'un bouton-lien qui restait souligné.
2026-09-09 00:05:26 +02:00

111 lines
4.1 KiB
C#

namespace MaBibli.Shared.Dtos;
/// <summary>
/// Une série telle qu'exposée par l'API — trilogie, cycle, intégrale.
/// </summary>
/// <remarks>
/// <b>La liste est rendue à plat</b>, 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 <i>et</i> le
/// détail — donc un seul instantané à tenir à jour.
/// </remarks>
public record SerieDto
{
public required int Id { get; init; }
public required string Titre { get; init; }
/// <summary>La série qui contient celle-ci, si elle fait partie d'un cycle.</summary>
public int? SerieParenteId { get; init; }
/// <summary>Rang dans la série parente. Sans objet à la racine.</summary>
public int Position { get; init; }
/// <summary>Les tomes, dans l'ordre de <b>lecture</b>.</summary>
public IReadOnlyList<ElementSerieDto> Elements { get; init; } = [];
/// <summary>Qui a créé la série. Trace d'affichage : la série est commune au foyer.</summary>
public string? AjoutePar { get; init; }
/// <summary>Tomes possédés sur tomes recensés — « 4 sur 7 », le cœur de l'écran.</summary>
public int NombrePossedes => Elements.Count(e => e.Possede);
}
/// <summary>
/// Une place dans l'ordre de lecture, occupée ou non.
/// </summary>
/// <remarks>
/// ⚠️ Un élément sans <see cref="LivreId"/> n'est <b>pas</b> une anomalie : c'est un tome qu'on
/// ne possède pas, et c'est précisément ce que l'écran doit montrer.
/// </remarks>
public record ElementSerieDto
{
public required int Id { get; init; }
public int Position { get; init; }
/// <summary>Titre du tome : celui du livre quand il est rattaché, sinon celui qui a été saisi.</summary>
public required string Titre { get; init; }
/// <summary>Le numéro imprimé sur le livre. <c>null</c> = inconnu.</summary>
public string? Numero { get; init; }
public int? LivreId { get; init; }
public bool Possede => LivreId is not null;
/// <summary>Auteurs du livre rattaché, pour ne pas avoir à ouvrir sa fiche.</summary>
public string? Auteurs { get; init; }
/// <summary>À qui le tome est prêté, s'il est dehors. Commun au foyer, comme tout prêt.</summary>
public string? PreteA { get; init; }
}
/// <summary>Charge utile de création ou de renommage d'une série.</summary>
public record EnregistrementSerie
{
public string Titre { get; set; } = string.Empty;
/// <summary>Série parente, pour ranger une trilogie dans un cycle. <c>null</c> = à la racine.</summary>
public int? SerieParenteId { get; set; }
}
/// <summary>
/// Charge utile d'ajout d'un tome : soit un livre du catalogue, soit un simple titre.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public record AjoutElementSerie
{
/// <summary>Le numéro imprimé sur le livre — facultatif.</summary>
public string? Numero { get; set; }
/// <summary>Livre du catalogue à placer ici. <c>null</c> = un tome qu'on ne possède pas.</summary>
public int? LivreId { get; set; }
/// <summary>Titre du tome. Obligatoire sans livre ; repris du livre sinon.</summary>
public string? Titre { get; set; }
}
/// <summary>Nouvel ordre de lecture : la liste <b>entière</b> des identifiants d'éléments.</summary>
/// <remarks>
/// 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.
/// </remarks>
public record OrdreElementsSerie
{
public List<int> Ids { get; set; } = [];
}
/// <summary>Nouvel ordre des séries directement contenues dans un cycle.</summary>
public record OrdreSeries
{
public List<int> Ids { get; set; } = [];
}
/// <summary>Déplacement d'une série dans l'ordre de lecture de son cycle.</summary>
public readonly record struct DeplacementSerie(int SerieId, int ParenteId, int Delta);