@*
Les champs d'un numéro de revue, partagés par l'ajout et la modification.
Un seul exemplaire, et pas deux blocs jumeaux : le formulaire d'ajout et celui de
modification doivent proposer exactement les mêmes champs, sinon une couverture ou une une
saisies à la création ne seraient plus modifiables ensuite — ce qui est précisément le cas
d'usage (on ajoute un numéro le jour où on l'achète, on en recopie la une plus tard).
⚠️ Aucun champ ne se lie DIRECTEMENT à « Saisie » : chacun passe par une propriété qui
prévient le parent (OnChangement). Blazor ne redessine que le composant qui a traité
l'événement — une frappe ici ne re-rendait donc pas l'écran qui porte le bouton
« Ajouter ce numéro », et celui-ci restait grisé jusqu'à ce qu'autre chose redessine le
parent (enregistrer la revue, par exemple). Voir CLAUDE.md.
*@
@*
⚠️ Un titre à la fois, et surtout PAS une ligne de titres séparés par des points-virgules :
voir SaisieListe, qui porte le pourquoi. Une virgule dans un titre (« Ukraine, deux ans
après ») n'a plus rien à couper, puisque plus rien ne découpe.
*@
@*
⚠️ Une URL, pas une photo. Aucune source ne donne la couverture d'un NUMÉRO : l'ISSN désigne
la revue, pas la parution. Et le projet ne stocke aucun fichier — « ebooks : fiches
uniquement » vaut ici aussi.
*@
@code {
[Parameter, EditorRequired] public AjoutNumeroRevue Saisie { get; set; } = default!;
///
/// Signale au parent que la saisie a changé, pour qu'il se redessine.
///
///
/// ⚠️ Sans cela, un bouton du parent qui dépend de la saisie reste figé. Blazor ne
/// redessine que le composant ayant traité l'événement : « Ajouter ce numéro » vit dans
/// l'écran de la revue, le champ « Numéro » vit ici, et le bouton restait donc désactivé
/// tant que rien d'autre ne re-rendait le parent — constaté en usage, où il fallait passer
/// par « Modifier la revue » puis « Enregistrer » pour le débloquer.
///
/// Tous les champs préviennent, pas seulement le numéro : aucun autre bouton n'en dépend
/// aujourd'hui, mais faire dépendre la correction de « lequel commande quoi » la referait
/// oublier au premier champ ajouté.
///
///
[Parameter] public EventCallback OnChangement { get; set; }
///
/// Les champs du numéro, servis par des propriétés plutôt que liés à :
/// c'est le seul endroit d'où prévenir le parent à coup sûr.
///
private string Numero
{
get => Saisie.Numero;
set { Saisie.Numero = value; Notifier(); }
}
private string? Note
{
get => Saisie.Note;
set { Saisie.Note = value; Notifier(); }
}
private string? CoverUrl
{
get => Saisie.CoverUrl;
set { Saisie.CoverUrl = value; Notifier(); }
}
///
/// Le parent est prévenu sans être attendu : InvokeAsync ne fait que demander un
/// nouveau rendu, et un setter de propriété ne peut de toute façon rien attendre.
///
private void Notifier() => _ = OnChangement.InvokeAsync();
///
/// Date affichée par le champ, en local.
///
///
/// ⚠️ Le <input type="date"> produit une date sans fuseau. Elle est déclarée
/// locale ici et convertie en UTC, comme toutes les dates du projet : sans cela la parution
/// se décale d'un jour pour la moitié du globe. La conversion se fait dans le composant
/// pour que les deux écrans qui s'en servent ne puissent pas l'oublier chacun de leur côté.
///
private DateTime? Parution
{
get => Saisie.DateParution?.ToLocalTime().Date;
set
{
Saisie.DateParution = value is { } date
? DateTime.SpecifyKind(date, DateTimeKind.Local).ToUniversalTime()
: null;
Notifier();
}
}
[Parameter] public EventCallback OnEntree { get; set; }
private async Task SurTouche(KeyboardEventArgs e)
{
if (e.Key == "Enter")
{
await OnEntree.InvokeAsync(e);
}
}
}