@* Formulaire d'une fiche livre, partagé par l'ajout (ISBN ou manuel) et l'édition. Le pré-remplissage par ISBN est une AIDE, pas une contrainte : tous les champs restent modifiables, et une fiche incomplète peut toujours être complétée à la main (CLAUDE.md). *@
@if (!string.IsNullOrEmpty(Saisie.CoverUrl) || !string.IsNullOrWhiteSpace(Saisie.Titre)) {
} @* Un seul champ, plusieurs auteurs : le point-virgule les sépare. La virgule est déjà prise par la forme bibliographique « Zola, Émile », qu'on doit pouvoir taper telle quelle. Le serveur rapproche ensuite les variantes sûres d'un auteur déjà connu. *@ @* Les rôles n'apparaissent qu'à partir de DEUX auteurs, et c'est délibéré : un roman n'a qu'un signataire dont le rôle ne se pose pas, et une ligne de boutons sous chaque saisie n'apprendrait rien. La question « qui écrit, qui dessine ? » ne se pose qu'à plusieurs. Le défaut reste « non précisé » : on ne remplit pas une case à la place de l'utilisateur. *@ @if (Saisie.Auteurs.Count > 1) {
Rôles (facultatif — utile pour une BD) @foreach (var (auteur, index) in Saisie.Auteurs.Select((a, i) => (a, i))) {
@auteur.Nom
@foreach (var role in Roles) { }
}
} @* Le format n'est plus affiché dans les listes que pour les ebooks : un livre y est donc physique par défaut. Cette valeur DOIT rester présélectionnée ici, sinon on créerait des fiches sans format en croyant que « rien d'affiché = physique ». C'est le cas sans code particulier : Format.Physique vaut 0, valeur par défaut de l'énumération, et le segment correspondant est donc actif dès l'ouverture. *@
Format (physique par défaut)
@foreach (var format in Formats) { }
@* ⚠️ Le défaut est « non précisé », PAS « roman » : on ne remplit pas une case à la place de l'utilisateur. C'est aussi ce qui rend l'étiquette honnête dans les listes — elle ne s'affiche que lorsqu'un type a été choisi. *@
Type (facultatif)
@foreach (var type in Types) { }
Statut de lecture (le vôtre)
@if (!string.IsNullOrEmpty(Erreur)) { } @* Un enregistrement impossible se dit AVANT le clic : un bouton qui échoue en silence est pire que pas de bouton du tout (CLAUDE.md, stratégie hors-ligne). *@ @if (!string.IsNullOrEmpty(MessageBlocage)) {

@MessageBlocage

}
@if (OnAnnuler.HasDelegate) { }
@code { private static readonly Format[] Formats = Enum.GetValues(); private static readonly TypeDocument[] Types = Enum.GetValues(); private static readonly RoleAuteur[] Roles = Enum.GetValues(); /// /// Pose le rôle d'un auteur. /// /// /// est un record : on remplace l'entrée plutôt que de la muter, /// et la liste reste celle que la propriété Auteur saura relire pour préserver les /// rôles à la frappe suivante. /// private void PoserRole(int index, RoleAuteur role) => Saisie.Auteurs[index] = Saisie.Auteurs[index] with { Role = role }; [Parameter, EditorRequired] public EnregistrementLivre Saisie { get; set; } = new(); [Parameter] public string LibelleValidation { get; set; } = "Enregistrer"; [Parameter] public string? Erreur { get; set; } [Parameter] public bool EnCours { get; set; } /// /// Raison pour laquelle l'enregistrement est impossible (typiquement l'absence de réseau). /// Renseignée, elle désactive la validation et s'affiche : la saisie reste lisible, mais /// l'utilisateur sait pourquoi il ne peut pas valider. /// [Parameter] public string? MessageBlocage { get; set; } private bool Bloque => !string.IsNullOrEmpty(MessageBlocage); [Parameter] public EventCallback OnValider { get; set; } [Parameter] public EventCallback OnAnnuler { get; set; } private Task Valider() => OnValider.InvokeAsync(); }