Fait saisir un par un ce qui se saisissait sur une ligne à séparateurs
Les thèmes et les auteurs souffraient du défaut corrigé hier sur les unes : un champ relié à chaque frappe sur une propriété qui découpait puis recomposait la liste, donc un séparateur intapable. Ils passent au même geste — écrire, Entrée, puis modifier ou retirer chaque ligne — et le composant est partagé plutôt que recopié une troisième fois. Le bloc des rôles se fond dans la liste des auteurs : il listait les mêmes noms une seconde fois. Renommer une ligne conserve son rôle, parce qu'on corrige un nom au lieu de reconstruire la liste. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,9 +21,9 @@
|
||||
@*
|
||||
⚠️ L'ORDRE DES CHAMPS EST UNE DÉCISION (lot Q, 2026-08-21), pas une mise en page.
|
||||
|
||||
Type de document, puis thèmes, puis auteurs, puis rôles : c'est l'ordre dans lequel on
|
||||
regarde un livre qu'on tient en main, et surtout le type COMMANDE LA SUITE de la saisie —
|
||||
les rôles ne se posent que là. Relégué en bas, il obligeait à descendre tout le formulaire
|
||||
Type de document, puis thèmes, puis auteurs (chacun avec son rôle) : c'est l'ordre dans
|
||||
lequel on regarde un livre qu'on tient en main, et surtout le type COMMANDE LA SUITE de
|
||||
la saisie — les rôles ne se posent que là. Relégué en bas, il obligeait à descendre tout le formulaire
|
||||
pour dire « c'est une BD », c'est-à-dire après avoir saisi ce qui en dépend.
|
||||
|
||||
⚠️ Remonter le champ le rend visible ; le PRÉREMPLIR écrirait quelque chose de faux. Le
|
||||
@@ -46,61 +46,48 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<label class="champ">
|
||||
@* Point-virgule, comme le champ des auteurs juste en dessous : trois champs voisins du
|
||||
même formulaire ne doivent pas se saisir de trois façons. La virgule reste acceptée —
|
||||
un thème n'en contient jamais, contrairement à un titre d'article à la une. *@
|
||||
<span class="champ-libelle">
|
||||
Thèmes <span class="champ-aide">(séparés par des points-virgules)</span>
|
||||
</span>
|
||||
<input class="champ-saisie" type="text" @bind="Saisie.ThemesTexte" @bind:event="oninput"
|
||||
placeholder="Fantasy ; aventure ; space opera" autocomplete="off" />
|
||||
</label>
|
||||
@*
|
||||
⚠️ Thèmes et auteurs se saisissent UN PAR UN, et non plus sur une ligne à séparateurs.
|
||||
Le champ unique se reliait à chaque frappe sur une propriété qui découpait puis
|
||||
recomposait la liste : le point-virgule tapé y était élagué (entrée vide) et l'espace
|
||||
qui le suit rogné — le séparateur était le seul caractère qu'on ne pouvait pas taper.
|
||||
Voir CLAUDE.md.
|
||||
*@
|
||||
<SaisieListe Valeurs="Saisie.Themes" Libelle="Thèmes" Aide=" (un par un : tapez, puis Entrée)"
|
||||
Placeholder="dark fantasy" MessageDoublon="Ce thème est déjà sur ce livre."
|
||||
OnChangement="StateHasChanged" />
|
||||
|
||||
@*
|
||||
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.
|
||||
*@
|
||||
<label class="champ">
|
||||
<span class="champ-libelle">
|
||||
Auteur<span class="champ-aide"> (plusieurs : séparez par « ; »)</span>
|
||||
</span>
|
||||
<input class="champ-saisie" type="text" @bind="Saisie.Auteur" @bind:event="oninput"
|
||||
placeholder="Prénom Nom ; Prénom Nom" autocomplete="off" />
|
||||
</label>
|
||||
Un auteur par ligne, et son RÔLE avec lui.
|
||||
|
||||
@*
|
||||
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)
|
||||
{
|
||||
<fieldset class="champ">
|
||||
<legend class="champ-libelle">
|
||||
Rôles<span class="champ-aide"> (facultatif — utile pour une BD)</span>
|
||||
</legend>
|
||||
⚠️ Le rôle vit sur le LIEN, pas sur la personne : le même auteur scénarise un album et
|
||||
dessine le suivant. C'est aussi pourquoi renommer une ligne conserve son rôle
|
||||
(NomsAuteurs) — on corrige un nom, on ne désigne pas quelqu'un d'autre.
|
||||
|
||||
@foreach (var (auteur, index) in Saisie.Auteurs.Select((a, i) => (a, i)))
|
||||
⚠️ Les rôles n'apparaissent qu'à partir de DEUX auteurs, décision inchangée : un roman
|
||||
n'a qu'un signataire dont le rôle ne se pose pas. Le défaut reste « non précisé ».
|
||||
*@
|
||||
<SaisieListe Valeurs="_noms" Libelle="Auteurs" Aide=" (un par un : tapez, puis Entrée)"
|
||||
Placeholder="Prénom Nom, ou Nom, Prénom"
|
||||
MessageDoublon="Cet auteur est déjà sur ce livre."
|
||||
OnChangement="StateHasChanged">
|
||||
<Complement Context="index">
|
||||
@if (Saisie.Auteurs.Count > 1)
|
||||
{
|
||||
<div class="ligne-role" @key="index">
|
||||
<span class="nom-role">@auteur.Nom</span>
|
||||
<div class="segments">
|
||||
@foreach (var role in Roles)
|
||||
{
|
||||
<button type="button"
|
||||
class="segment @(auteur.Role == role ? "segment-actif" : null)"
|
||||
@onclick="() => PoserRole(index, role)">
|
||||
@Libelles.RoleAuteur(role)
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
<div class="segments segments-role" role="group"
|
||||
aria-label="@($"Rôle de {Saisie.Auteurs[index].Nom}")">
|
||||
@foreach (var role in Roles)
|
||||
{
|
||||
<button type="button"
|
||||
class="segment @(Saisie.Auteurs[index].Role == role ? "segment-actif" : null)"
|
||||
@onclick="() => PoserRole(index, role)">
|
||||
@Libelles.RoleAuteur(role)
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</fieldset>
|
||||
}
|
||||
</Complement>
|
||||
</SaisieListe>
|
||||
|
||||
@*
|
||||
Le format n'est plus affiché dans les listes que pour les ebooks : un livre y est donc
|
||||
@@ -212,6 +199,27 @@
|
||||
private void PoserRole(int index, RoleAuteur role) =>
|
||||
Saisie.Auteurs[index] = Saisie.Auteurs[index] with { Role = role };
|
||||
|
||||
/// <summary>
|
||||
/// Les noms des auteurs, vus comme une liste de chaînes par <c>SaisieListe</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ⚠️ Sa <b>référence doit rester stable</b> tant que la saisie ne change pas : le composant
|
||||
/// se remet à zéro quand la liste qu'on lui prête change d'identité, et il perdrait donc à
|
||||
/// chaque rendu ce qui est en cours de frappe.
|
||||
/// </remarks>
|
||||
private NomsAuteurs _noms = default!;
|
||||
|
||||
private EnregistrementLivre? _saisiePrecedente;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (!ReferenceEquals(_saisiePrecedente, Saisie))
|
||||
{
|
||||
_saisiePrecedente = Saisie;
|
||||
_noms = new NomsAuteurs(Saisie.Auteurs);
|
||||
}
|
||||
}
|
||||
|
||||
[Parameter, EditorRequired] public EnregistrementLivre Saisie { get; set; } = new();
|
||||
|
||||
[Parameter] public string LibelleValidation { get; set; } = "Enregistrer";
|
||||
|
||||
Reference in New Issue
Block a user