Files
mabibli/MaBibli.Client/Pages/EditionSouhaitRevue.razor
Mathieu LimonierandClaude Opus 5 6a6d745af4 MaBibli 1.0.0
Gestion de bibliothèque personnelle auto-hébergée : catalogue, prêts,
scan de code-barres, consultation hors-ligne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 22:36:16 +02:00

145 lines
4.4 KiB
Plaintext

@page "/souhaits/revues/{Id:int}/edition"
@inject ServiceLivresApi Api
@inject EtatReseau Reseau
@inject NavigationManager Navigation
@implements IDisposable
@*
Le même geste que pour une envie de livre, sur la table sœur : écran dédié, mode dans
l'adresse. Les deux formulaires ne se fondent pas en un seul — une revue n'a ni auteur, ni
éditeur, ni ISBN, et un formulaire à moitié grisé se lit plus mal que deux formulaires courts.
*@
<PageTitle>MaBibli — modifier une envie de revue</PageTitle>
<h1 class="titre-page">Modifier une envie de revue</h1>
@if (_erreur is not null)
{
<p class="message-erreur" role="alert">@_erreur</p>
}
@if (_introuvable)
{
<p class="message-discret">
@(Reseau.EnLigne
? "Cette envie n'existe plus dans votre liste."
: "Cette envie n'est pas dans les données enregistrées sur cet appareil.")
</p>
}
else if (_saisie is null)
{
<Patience Message="Ouverture de l'envie…" />
}
else
{
<div class="formulaire">
<label class="champ">
<span class="champ-libelle">Titre de la revue <span class="obligatoire" aria-hidden="true">*</span></span>
<input class="champ-saisie" type="text" @bind="_saisie.Titre" @bind:event="oninput"
placeholder="Médor" autocomplete="off" />
</label>
<label class="champ">
<span class="champ-libelle">
Numéro <span class="champ-aide">(vide = la revue entière)</span>
</span>
<input class="champ-saisie" type="text" @bind="_saisie.Numero" @bind:event="oninput"
placeholder="43, hors-série 7…" autocomplete="off" />
</label>
@* La saisie garde ce qui est tapé : le tiret est posé à l'enregistrement, jamais à la
frappe — sinon il se battrait avec le curseur. *@
<label class="champ">
<span class="champ-libelle">ISSN <span class="champ-aide">(facultatif)</span></span>
<input class="champ-saisie" type="text" @bind="_saisie.Issn" @bind:event="oninput"
placeholder="2466-6718" autocomplete="off" />
</label>
<label class="champ">
<span class="champ-libelle">Note</span>
<input class="champ-saisie" type="text" @bind="_saisie.Note" @bind:event="oninput"
placeholder="« vu chez le dentiste »…" autocomplete="off" />
</label>
@if (!Reseau.EnLigne)
{
<p class="message-avertissement" role="status">@EtatReseau.MotifHorsLigne</p>
}
<div class="actions-formulaire">
<button type="button" class="bouton bouton-principal"
disabled="@(_enCours || !Reseau.EnLigne || string.IsNullOrWhiteSpace(_saisie.Titre))"
title="@MotifBlocage" @onclick="EnregistrerAsync">
@(_enCours ? "Enregistrement…" : "Enregistrer")
</button>
<a class="bouton bouton-discret" href="souhaits">Annuler</a>
</div>
</div>
}
@code {
[Parameter] public int Id { get; set; }
private EnregistrementRevueSouhaitee? _saisie;
private bool _introuvable;
private bool _enCours;
private string? _erreur;
protected override async Task OnInitializedAsync()
{
Reseau.Change += SurChangementReseau;
await ChargerAsync();
}
private void SurChangementReseau() => _ = InvokeAsync(StateHasChanged);
public void Dispose() => Reseau.Change -= SurChangementReseau;
private string? MotifBlocage => Reseau.EnLigne ? null : EtatReseau.MotifHorsLigne;
private async Task ChargerAsync()
{
var envies = await Api.ListerRevuesSouhaiteesAsync();
var envie = envies.FirstOrDefault(e => e.Id == Id);
if (envie is null)
{
_introuvable = true;
return;
}
_saisie = new EnregistrementRevueSouhaitee
{
Titre = envie.Titre,
Numero = envie.Numero,
Issn = envie.Issn,
Note = envie.Note,
};
}
private async Task EnregistrerAsync()
{
if (_saisie is null)
{
return;
}
_enCours = true;
_erreur = null;
var resultat = await Api.ModifierRevueSouhaiteeAsync(Id, _saisie);
_enCours = false;
if (!resultat.EstOk)
{
_erreur = resultat.Erreur;
return;
}
Navigation.NavigateTo("souhaits");
}
}