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>
145 lines
4.4 KiB
Plaintext
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");
|
|
}
|
|
}
|