227 lines
8.1 KiB
Plaintext
227 lines
8.1 KiB
Plaintext
@inject ServiceLivresApi Api
|
|
|
|
@*
|
|
Panneau de modification en lot, ouvert depuis la fiche série une fois des tomes cochés.
|
|
|
|
⚠️ Reprend le DESIGN de FormulaireLivre.razor (mêmes composants, même ordre de champs), mais
|
|
chaque champ est précédé d'une case « Modifier… » : sans elle, la valeur par défaut d'un champ
|
|
(« NonPrecise », « Physique »…) est déjà une vraie valeur, et l'appliquer à tous les livres
|
|
sélectionnés écraserait un champ qu'on ne voulait pas toucher (CLAUDE.md, invariant 10).
|
|
Un champ non coché ne s'affiche pas — c'est ce qui rend visible ce qui va être écrasé.
|
|
*@
|
|
<div class="formulaire">
|
|
<p class="message-avertissement" role="status">
|
|
Les champs cochés remplacent la valeur existante sur chacun des @NombreLivres livres
|
|
sélectionnés — pour les auteurs, une liste vide les retire tous.
|
|
</p>
|
|
|
|
<fieldset class="champ">
|
|
<legend class="champ-libelle">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierType" />
|
|
<span>Type</span>
|
|
</label>
|
|
</legend>
|
|
@if (Saisie.ModifierType)
|
|
{
|
|
<div class="segments">
|
|
@foreach (var type in Types)
|
|
{
|
|
<button type="button"
|
|
class="segment @Libelles.ClasseTypeDocument(type) @(Saisie.TypeDocument == type ? "segment-actif" : null)"
|
|
@onclick="() => Saisie.TypeDocument = type">
|
|
@Libelles.TypeDocument(type)
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
</fieldset>
|
|
|
|
<div class="champ">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierThemes" />
|
|
<span>Thèmes</span>
|
|
</label>
|
|
@if (Saisie.ModifierThemes)
|
|
{
|
|
<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à dans la liste."
|
|
Suggestions="_themesConnus"
|
|
OnChangement="StateHasChanged" />
|
|
}
|
|
</div>
|
|
|
|
<div class="champ">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierAuteurs" />
|
|
<span>Auteurs</span>
|
|
</label>
|
|
@if (Saisie.ModifierAuteurs)
|
|
{
|
|
<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à dans la liste."
|
|
OnChangement="StateHasChanged">
|
|
<Complement Context="index">
|
|
@if (Saisie.Auteurs.Count > 1)
|
|
{
|
|
<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>
|
|
}
|
|
</Complement>
|
|
</SaisieListe>
|
|
}
|
|
</div>
|
|
|
|
<fieldset class="champ">
|
|
<legend class="champ-libelle">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierFormat" />
|
|
<span>Format</span>
|
|
</label>
|
|
</legend>
|
|
@if (Saisie.ModifierFormat)
|
|
{
|
|
<div class="segments">
|
|
@foreach (var format in Formats)
|
|
{
|
|
<button type="button"
|
|
class="segment @(Saisie.Format == format ? "segment-actif" : null)"
|
|
@onclick="() => Saisie.Format = format">
|
|
@Libelles.Format(format)
|
|
</button>
|
|
}
|
|
</div>
|
|
}
|
|
</fieldset>
|
|
|
|
<div class="champ">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierEditeur" />
|
|
<span>Éditeur</span>
|
|
</label>
|
|
@if (Saisie.ModifierEditeur)
|
|
{
|
|
<input class="champ-saisie" type="text" @bind="Saisie.Editeur" @bind:event="oninput"
|
|
autocomplete="off" />
|
|
}
|
|
</div>
|
|
|
|
<fieldset class="champ">
|
|
<legend class="champ-libelle">
|
|
<label class="bascule">
|
|
<input type="checkbox" @bind="Saisie.ModifierStatut" />
|
|
<span>Statut de lecture <span class="champ-aide">(le vôtre)</span></span>
|
|
</label>
|
|
</legend>
|
|
@if (Saisie.ModifierStatut)
|
|
{
|
|
<ChoixStatut Valeur="Saisie.Statut" ValeurChanged="s => Saisie.Statut = s" />
|
|
}
|
|
</fieldset>
|
|
|
|
@if (!string.IsNullOrEmpty(Erreur))
|
|
{
|
|
<p class="message-erreur" role="alert">@Erreur</p>
|
|
}
|
|
|
|
@if (!string.IsNullOrEmpty(MessageBlocage))
|
|
{
|
|
<p class="message-avertissement" role="status">@MessageBlocage</p>
|
|
}
|
|
|
|
<div class="actions-formulaire">
|
|
<button type="button" class="bouton bouton-principal"
|
|
disabled="@(EnCours || Bloque || Saisie.AucunChamp)"
|
|
title="@(Saisie.AucunChamp ? "Cochez au moins un champ à modifier." : MessageBlocage)"
|
|
@onclick="Valider">
|
|
@(EnCours ? "Enregistrement…" : LibelleValidation)
|
|
</button>
|
|
|
|
@if (OnAnnuler.HasDelegate)
|
|
{
|
|
<button type="button" class="bouton bouton-discret" disabled="@EnCours"
|
|
@onclick="OnAnnuler">
|
|
Annuler
|
|
</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@code {
|
|
private static readonly Format[] Formats = Enum.GetValues<Format>();
|
|
|
|
private static readonly TypeDocument[] Types = Enum.GetValues<TypeDocument>();
|
|
|
|
private static readonly RoleAuteur[] Roles = Enum.GetValues<RoleAuteur>();
|
|
|
|
private void PoserRole(int index, RoleAuteur role) =>
|
|
Saisie.Auteurs[index] = Saisie.Auteurs[index] with { Role = role };
|
|
|
|
/// <summary>Voir la remarque équivalente sur FormulaireLivre.razor : référence stable tant
|
|
/// que la saisie ne change pas, sans quoi SaisieListe se remet à zéro à chaque frappe.</summary>
|
|
private NomsAuteurs? _noms;
|
|
|
|
private NomsAuteurs Noms => _noms ??= new NomsAuteurs(Saisie.Auteurs);
|
|
|
|
private SaisieLot? _saisiePrecedente;
|
|
|
|
private IReadOnlyList<string> _themesConnus = [];
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
try
|
|
{
|
|
_themesConnus =
|
|
[
|
|
.. (await Api.ListerAsync(new CritereLivres()))
|
|
.SelectMany(l => l.Themes)
|
|
.DistinctBy(NormalisationTexte.Normaliser, StringComparer.Ordinal)
|
|
.OrderBy(NormalisationTexte.Normaliser, StringComparer.Ordinal),
|
|
];
|
|
}
|
|
catch (Exception)
|
|
{
|
|
_themesConnus = [];
|
|
}
|
|
}
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
if (!ReferenceEquals(_saisiePrecedente, Saisie))
|
|
{
|
|
_saisiePrecedente = Saisie;
|
|
_noms = null;
|
|
}
|
|
}
|
|
|
|
[Parameter, EditorRequired] public SaisieLot Saisie { get; set; } = new();
|
|
|
|
[Parameter] public int NombreLivres { get; set; }
|
|
|
|
[Parameter] public string LibelleValidation { get; set; } = "Appliquer";
|
|
|
|
[Parameter] public string? Erreur { get; set; }
|
|
|
|
[Parameter] public bool EnCours { get; set; }
|
|
|
|
[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();
|
|
}
|