Ajouter la liste d'envies personnelle, son export et la bibliographie par auteur
La liste d'envies vit dans une table séparée (LivreSouhaite) plutôt que dans un statut de plus sur Livre : un livre souhaité n'est pas possédé, et le loger dans Livres l'aurait fait entrer dans le catalogue, les compteurs et les prêts, au prix d'un « et qui n'est pas souhaité » à répéter dans chaque lecture. La portée est personnelle, comme le statut de lecture — mais ici Utilisateur est une vraie frontière : toute lecture filtre dessus. Bibliographie : SRU BnF interrogé par bib.author, vérifié le 2026-08-18. Deux filtres mesurés sur des réponses réelles sont indispensables — le type de document (l'index mêle livres audio, jeux et spectacles) et surtout l'auteur réel de la notice, « all » rapprochant les mots sur l'ensemble des auteurs : « Émile Zola » remonte sinon toute l'œuvre de sa fille Denise Le Blond-Zola. Les rééditions sont regroupées par clé d'œuvre (183 notices Werber -> 51 œuvres). Le rapprochement avec l'étagère se fait par titre, pas par ISBN, qui désigne une édition et non une œuvre ; ses limites sont dites à l'écran. Export en deux formats, tous deux du texte sans dépendance : .txt groupé par auteur pour la librairie, .csv à séparateur point-virgule et BOM pour le tableur. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -231,6 +231,63 @@ public sealed class ServiceLivresApi(HttpClient http)
|
||||
};
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Liste d'envies et bibliographie par auteur.
|
||||
// Bloc ajouté en fin de classe pour rester bien délimité.
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
/// La liste d'envies <b>de l'utilisateur courant</b>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Comme pour le statut de lecture, le client ne transmet aucune identité : le serveur sait
|
||||
/// qui appelle. Il n'existe volontairement pas de moyen de demander la liste d'un autre.
|
||||
/// </remarks>
|
||||
public async Task<IReadOnlyList<SouhaitDto>> ListerSouhaitsAsync(CancellationToken ct = default) =>
|
||||
await http.GetFromJsonAsync<List<SouhaitDto>>("api/souhaits", Json, ct) ?? [];
|
||||
|
||||
public async Task<ResultatApi<SouhaitDto>> AjouterSouhaitAsync(
|
||||
EnregistrementSouhait saisie, CancellationToken ct = default)
|
||||
{
|
||||
var reponse = await http.PostAsJsonAsync("api/souhaits", saisie, Json, ct);
|
||||
return await InterpreterAsync<SouhaitDto>(reponse, ct);
|
||||
}
|
||||
|
||||
public async Task<string?> SupprimerSouhaitAsync(int id, CancellationToken ct = default)
|
||||
{
|
||||
var reponse = await http.DeleteAsync($"api/souhaits/{id}", ct);
|
||||
return reponse.IsSuccessStatusCode ? null : await MessageErreurAsync(reponse, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adresse de téléchargement d'un export.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Le fichier n'est pas récupéré par ce service : un simple lien suffit, le serveur pose un
|
||||
/// <c>Content-Disposition: attachment</c> et le navigateur enregistre. Passer par
|
||||
/// <see cref="HttpClient"/> obligerait à fabriquer une URL d'objet en JavaScript pour un
|
||||
/// résultat identique.
|
||||
/// <para>
|
||||
/// ⚠️ Le lien <b>doit</b> porter l'attribut <c>download</c> : sans lui, le routeur Blazor
|
||||
/// intercepte le clic comme une navigation interne et affiche sa page « introuvable » au
|
||||
/// lieu de laisser le navigateur télécharger.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static string UrlExportSouhaits(FormatExportSouhaits format) =>
|
||||
format == FormatExportSouhaits.Csv ? "api/souhaits/export.csv" : "api/souhaits/export.txt";
|
||||
|
||||
/// <summary>
|
||||
/// Bibliographie d'un auteur d'après la BnF. <c>null</c> si l'auteur n'existe pas.
|
||||
/// </summary>
|
||||
public async Task<BibliographieDto?> ObtenirBibliographieAsync(
|
||||
int auteurId, CancellationToken ct = default)
|
||||
{
|
||||
var reponse = await http.GetAsync($"api/auteurs/{auteurId}/bibliographie", ct);
|
||||
return reponse.StatusCode == HttpStatusCode.NotFound
|
||||
? null
|
||||
: await LireAsync<BibliographieDto>(reponse, ct);
|
||||
}
|
||||
|
||||
private sealed record ErreurApi(string? Erreur);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user