185 lines
7.0 KiB
C#
185 lines
7.0 KiB
C#
using MijnBesluit.Client;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.Web;
|
|
|
|
namespace MijnBesluit.AppUi;
|
|
|
|
/// <summary>
|
|
/// Gedeelde basis voor de schermen achter het inloggen: haalt de gegevens op, houdt één
|
|
/// foutmelding bij en stuurt wie niet is aangemeld naar het inlogscherm.
|
|
/// </summary>
|
|
public abstract class SchermBasis : ComponentBase, IDisposable
|
|
{
|
|
[Inject] protected AppToestand Toestand { get; set; } = default!;
|
|
[Inject] protected NavigationManager Navigatie { get; set; } = default!;
|
|
[Inject] private VernieuwSignaal Vernieuwen { get; set; } = default!;
|
|
|
|
/// <summary>Wordt getoond in een rode balk bovenaan het scherm.</summary>
|
|
protected string? Fout { get; set; }
|
|
|
|
/// <summary>Er loopt iets; knoppen zijn dan uit zodat er niet twee keer wordt gedrukt.</summary>
|
|
protected bool Bezig { get; set; }
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
Toestand.Veranderd += OpVerandering;
|
|
|
|
// Op PersoonId en niet op IsAangemeld: een bewaard token zegt alleen dat we ooit zijn
|
|
// ingelogd, niet dat de app al weet wie hij is. Lukte het oppakken van de sessie de
|
|
// vorige keer niet omdat er even geen verbinding was, dan staat het token er nog en
|
|
// proberen we het hier gewoon opnieuw.
|
|
//
|
|
// En naar het inlogscherm alleen als er daarna echt geen token meer is. Dat betekent
|
|
// dat de server de sessie niet meer kent - de enige goede reden om iemand opnieuw te
|
|
// laten inloggen. Een haperende verbinding hoort dat niet te doen: dan komt er een rode
|
|
// balk "geen verbinding" en blijft de sessie staan.
|
|
if (Toestand.PersoonId == 0 && !await Toestand.HervatAsync() && !Toestand.IsAangemeld)
|
|
{
|
|
Navigatie.NavigateTo("/inloggen");
|
|
return;
|
|
}
|
|
|
|
await LaadAsync();
|
|
|
|
// Alleen het scherm dat nu open staat luistert naar het trek-naar-beneden-gebaar; zie
|
|
// VernieuwSignaal. Er wordt niet naar Bezig gekeken - dat gebruiken de schermen zelf al
|
|
// voor hun eigen knoppen en zou hier de verversing kunnen blokkeren zonder reden.
|
|
Vernieuwen.Gevraagd += OpVernieuwenGevraagdAsync;
|
|
}
|
|
|
|
/// <summary>Hier haalt het scherm zijn eigen gegevens op.</summary>
|
|
protected virtual Task LaadAsync() => Task.CompletedTask;
|
|
|
|
private async Task OpVernieuwenGevraagdAsync()
|
|
{
|
|
await LaadAsync();
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Voert iets uit dat kan mislukken en zet de melding klaar. Zo staat in elk scherm maar
|
|
/// één keer de afhandeling van fouten, en blijft de knop niet hangen als het misgaat.
|
|
/// </summary>
|
|
protected async Task<bool> ProbeerAsync(Func<Task<Uitkomst>> werk)
|
|
{
|
|
Bezig = true;
|
|
Fout = null;
|
|
StateHasChanged();
|
|
try
|
|
{
|
|
var uitkomst = await werk();
|
|
if (!uitkomst.Gelukt) Fout = uitkomst.Melding;
|
|
return uitkomst.Gelukt;
|
|
}
|
|
finally
|
|
{
|
|
Bezig = false;
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enter of spatie op een tegel die je normaal aantikt. Zo'n tegel is geen knop voor de
|
|
/// browser, dus zonder dit is hij alleen met een vinger of muis te bedienen - en niet met
|
|
/// een toetsenbord of een schermlezer.
|
|
/// </summary>
|
|
protected static Task ToetsAsync(KeyboardEventArgs toets, Func<Task> doen) =>
|
|
toets.Key is "Enter" or " " ? doen() : Task.CompletedTask;
|
|
|
|
private void OpVerandering() => InvokeAsync(StateHasChanged);
|
|
|
|
public virtual void Dispose()
|
|
{
|
|
Toestand.Veranderd -= OpVerandering;
|
|
Vernieuwen.Gevraagd -= OpVernieuwenGevraagdAsync;
|
|
}
|
|
}
|
|
|
|
/// <summary>Kleine hulpmiddelen om waarden leesbaar op het scherm te zetten.</summary>
|
|
public static class Tonen
|
|
{
|
|
// De maandnamen komen niet uit de taalinstelling van het toestel. Die bepaalde ze eerst, en
|
|
// op een telefoon die op Engels staat las de lijst "9 June 2031" terwijl de rest van het
|
|
// scherm Nederlands is. Een app die maar in één taal bestaat hoort ook maar in één taal te
|
|
// rekenen.
|
|
//
|
|
// De lijst zelf staat in MijnBesluit.Client, naast de website-versie in het domein; een
|
|
// zelfcontrole houdt die twee gelijk. De website liep tegen precies hetzelfde aan.
|
|
private static string[] Maanden => MijnBesluit.Client.Datums.Maanden;
|
|
private static string[] KorteMaanden => MijnBesluit.Client.Datums.KorteMaanden;
|
|
|
|
public static string Datum(DateTime? moment)
|
|
{
|
|
if (moment is null) return "";
|
|
var d = moment.Value.ToLocalTime();
|
|
return $"{d.Day} {Maanden[d.Month - 1]} {d.Year}";
|
|
}
|
|
|
|
public static string DatumTijd(DateTime? moment)
|
|
{
|
|
if (moment is null) return "";
|
|
var d = moment.Value.ToLocalTime();
|
|
return $"{Datum(d)} om {d:HH:mm}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// De datum zoals hij op een tegel staat: "9 Jun. 2031". Daar telt elke pixel, en de maand
|
|
/// voluit duwde het jaartal van de regel af - "22 Septem...".
|
|
/// </summary>
|
|
public static string Kort(DateTime? moment)
|
|
{
|
|
if (moment is null) return "";
|
|
var d = moment.Value.ToLocalTime();
|
|
return $"{d.Day} {KorteMaanden[d.Month - 1]} {d.Year}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Hetzelfde voor een kale datum zonder tijd - een geboortedag, een sterfdag. Die hoort
|
|
/// niet omgerekend te worden naar een tijdzone: 9 juni is 9 juni, waar je ook bent.
|
|
/// </summary>
|
|
public static string Kort(DateOnly? dag) =>
|
|
dag is null ? "" : $"{dag.Value.Day} {KorteMaanden[dag.Value.Month - 1]} {dag.Value.Year}";
|
|
|
|
/// <summary>De nummers komen overeen met VaultCategory in het domein.</summary>
|
|
public static string Categorie(int categorie) => categorie switch
|
|
{
|
|
1 => "Uitvaartwens",
|
|
2 => "Polis",
|
|
3 => "Wachtwoord",
|
|
4 => "Apparaat",
|
|
5 => "Pincode",
|
|
6 => "Document",
|
|
7 => "Notitie",
|
|
8 => "Sociale media",
|
|
_ => "Overig"
|
|
};
|
|
|
|
/// <summary>
|
|
/// Hoe een relatie op het scherm heet. De lijst staat in MijnBesluit.Client, zodat de app en
|
|
/// de website er niet ieder een eigen versie van hebben.
|
|
/// </summary>
|
|
public static string Relatie(int relatie) => MijnBesluit.Client.Relaties.Naam(relatie);
|
|
|
|
public static string Vrijgave(int beleid) => beleid switch
|
|
{
|
|
0 => "Alleen voor mijzelf",
|
|
1 => "Na mijn overlijden",
|
|
2 => "Op een datum",
|
|
_ => ""
|
|
};
|
|
|
|
/// <summary>
|
|
/// Het tekentje bij de vrijgave. Het takje is hetzelfde als dat van Nalatenschap onderin,
|
|
/// en de kalender staat voor een datum - zo hoeft niemand een nieuwe taal te leren.
|
|
///
|
|
/// Voor "Alleen voor mijzelf" staat hier niets: dat ben jij, en daar hoort je eigen
|
|
/// profielfoto, geen plaatje. Het scherm zet daar een penning neer.
|
|
/// </summary>
|
|
public static string Vrijgaveteken(int beleid) => beleid switch
|
|
{
|
|
1 => "\U0001F33F", // takje, net als bij Nalatenschap
|
|
2 => "\U0001F4C5", // kalender
|
|
_ => ""
|
|
};
|
|
}
|