Auteurs cherchables et triables, filtre de prêt, rang dans les exports, couvertures d'envies

Auteurs
- Recherche et tri (par nom, ou du plus présent au moins présent), en mémoire : la liste
  est déjà chargée en entier — c'est elle qui sert l'instantané hors-ligne — et la filtrer
  côté serveur aurait rendu la page inutilisable sans réseau.
- Trois colonnes dont une seule est élastique : compteur à gauche sur une largeur figée,
  nom au milieu, actions à droite. Les compteurs et les boutons s'alignent alors d'une
  ligne à l'autre au lieu de suivre la longueur du nom.

Catalogue
- Filtre « À la maison / Prêtés », posé dans les deux implémentations (serveur et
  hors-ligne) et dans le test qui les confronte, avec un cas de prêt CLOS — c'est
  exactement là que les deux auraient pu diverger en silence.
- La ligne disparaît tant que rien n'est prêté, comme celles des formats et des types.

Envies
- ⚠️ Les couvertures manquaient parce que seul l'écran « ajouter une envie » remplissait
  CoverUrl : la bibliographie et les tomes manquants transmettent un ISBN mais aucune
  image. Le repli est posé à la LECTURE, donc il vaut aussi pour les envies déjà
  enregistrées, sans migration.
- Les exports .txt et .csv portent le rang d'envie. Le .txt en a le plus besoin : son
  groupement par auteur détruit précisément cet ordre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-20 20:42:13 +02:00
co-authored by Claude Opus 5
parent 83089d7479
commit 4fd67e4e3b
13 changed files with 344 additions and 24 deletions
+26 -3
View File
@@ -32,7 +32,8 @@ public class FiltreLivresLocalTests
private static Livre Livre(
int id, string titre, Auteur? auteur, Format format, Statut? statut,
TypeDocument type = TypeDocument.NonPrecise)
TypeDocument type = TypeDocument.NonPrecise,
string? preteA = null, bool pretClos = false)
{
var livre = new Livre
{
@@ -50,6 +51,20 @@ public class FiltreLivresLocalTests
livre.Statuts.Add(new StatutLecture { LivreId = id, Utilisateur = Lecteur, Statut = valeur });
}
if (preteA is not null)
{
// ⚠️ Un prêt CLOS ne doit pas compter comme « dehors ». C'est le point où les deux
// implémentations pourraient diverger sans qu'on s'en aperçoive : le serveur regarde
// DateRetour, le client un PreteA que le serveur a déjà résolu.
livre.Prets.Add(new Pret
{
LivreId = id,
Emprunteur = preteA,
DatePret = new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc),
DateRetour = pretClos ? new DateTime(2026, 2, 1, 0, 0, 0, DateTimeKind.Utc) : null,
});
}
return livre;
}
@@ -57,8 +72,9 @@ public class FiltreLivresLocalTests
[
Livre(1, "Germinal", Zola, Format.Physique, Statut.Lu, TypeDocument.Roman),
Livre(2, "La Bête humaine", Zola, Format.Numerique, Statut.ALire, TypeDocument.BandeDessinee),
Livre(3, "Le Horla", Maupassant, Format.Physique, Statut.EnCours, TypeDocument.Roman),
Livre(4, "Bel-Ami", Maupassant, Format.Numerique, null),
Livre(3, "Le Horla", Maupassant, Format.Physique, Statut.EnCours, TypeDocument.Roman,
preteA: "Marie"),
Livre(4, "Bel-Ami", Maupassant, Format.Numerique, null, preteA: "Paul", pretClos: true),
Livre(5, "Œuvres complètes", Zola, Format.Physique, Statut.ALire),
Livre(6, "L'Éducation sentimentale", null, Format.Physique, null),
];
@@ -76,6 +92,9 @@ public class FiltreLivresLocalTests
TypeDocument = l.TypeDocument,
DateAjout = DateTime.UtcNow,
Statut = l.Statuts.FirstOrDefault(s => s.Utilisateur == Lecteur)?.Statut,
// Ce que l'API expose : l'emprunteur du prêt EN COURS, rien de l'historique clos.
PreteA = l.Prets.FirstOrDefault(p => p.DateRetour is null)?.Emprunteur,
Auteurs = l.Auteurs
.Select(la => new AuteurDto { Id = la.AuteurId, Nom = la.Auteur!.Nom })
.ToList(),
@@ -104,6 +123,10 @@ public class FiltreLivresLocalTests
new CritereLivres { AuteurId = 1 },
new CritereLivres { AuteurId = 2 },
new CritereLivres { AuteurId = 99 },
new CritereLivres { Prete = true },
new CritereLivres { Prete = false },
new CritereLivres { Prete = false, Format = Format.Physique },
new CritereLivres { Prete = true, Recherche = "horla" },
new CritereLivres { Recherche = "zola", Format = Format.Physique, Statut = Statut.ALire },
new CritereLivres
{