Eerste commit
This commit is contained in:
@@ -0,0 +1,359 @@
|
||||
@page "/"
|
||||
@attribute [Authorize]
|
||||
@inject OverzichtService Overzichten
|
||||
@inject LegacyService NalatenschapService
|
||||
@inject AdvertentieService Adverteren
|
||||
@inject AccountService Accounts
|
||||
@inject SamenvoegService Samenvoegen
|
||||
@rendermode InteractiveServer
|
||||
|
||||
<PageTitle>MijnBesluit</PageTitle>
|
||||
|
||||
@* Het beginscherm, met dezelfde indeling als in de app: eerst wat er speelt, dan de tegels.
|
||||
De aantallen staan achter de titel in plaats van op een regel eronder, zodat de tegels
|
||||
laag blijven. *@
|
||||
|
||||
<AuthorizeView Context="auth">
|
||||
<Authorized>
|
||||
<h1>@Begroeting(auth.User.Naam())</h1>
|
||||
|
||||
@if (Fout is not null)
|
||||
{
|
||||
<div class="melding fout">@Fout</div>
|
||||
}
|
||||
|
||||
@if (Melding is not null)
|
||||
{
|
||||
<div class="melding goed">@Melding</div>
|
||||
}
|
||||
|
||||
@* Heeft iemand een profiel voor je aangemaakt op jouw adres? Dan staat die vraag hier,
|
||||
bovenaan, tot je hem beantwoordt. Alleen jij kunt zeggen of dat over jou gaat;
|
||||
koppelen op e-mailadres doet MijnBesluit niet. Zie docs/Identiteit.md. *@
|
||||
@foreach (var aantekening in Aantekeningen)
|
||||
{
|
||||
<div class="kaart" style="margin-bottom:1rem">
|
||||
<h2 style="margin-top:0">Ben jij dit?</h2>
|
||||
<p style="margin-top:0">
|
||||
<strong>@aantekening.Van</strong> heeft een profiel voor je aangemaakt op jouw
|
||||
e-mailadres@(aantekening.Relatie is { Length: > 0 } r ? $", als {r.ToLowerInvariant()}" : "").
|
||||
</p>
|
||||
<p class="zacht" style="margin-top:0">
|
||||
Ben jij dat, dan voegen we het bij je eigen profiel: wat hij over je heeft
|
||||
ingevuld komt bij jou te staan, en vanaf dat moment bepaal jij wat er staat.
|
||||
Ben jij het niet, dan blijft alles zoals het is en vragen we het niet nog eens.
|
||||
</p>
|
||||
<div class="knoppen">
|
||||
<button class="knop vol" disabled="@Bezig"
|
||||
@onclick="() => Overnemen(aantekening.PersoonId)">Ja, dat ben ik</button>
|
||||
<button class="knop rustig" disabled="@Bezig"
|
||||
@onclick="() => Afwijzen(aantekening.PersoonId)">Nee, dat ben ik niet</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Gegevens is { Regels.Count: > 0 })
|
||||
{
|
||||
<div class="stapel speelt">
|
||||
@foreach (var regel in Gegevens.Regels)
|
||||
{
|
||||
<div class="regel @(regel.Soort == "overlijden" ? "let-op" : "")">
|
||||
<span class="teken">@Teken(regel.Soort)</span>
|
||||
<div class="groei">
|
||||
<div>@regel.Tekst</div>
|
||||
@if (regel.Datum is { } datum)
|
||||
{
|
||||
<div class="zacht">@Datums.MetDag(datum)</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (Gegevens.Regels.Any(r => r.Soort == "overlijden"))
|
||||
{
|
||||
<button class="knop" style="margin-bottom:1rem" disabled="@Bezig" @onclick="IkBenErNog">
|
||||
Ik ben er nog
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
@* De advertentie staat hier en niet bovenaan: "wat er speelt" gaat voor. Iemand die net
|
||||
leest dat er een overlijden op zijn naam is gemeld, hoort daar geen reclame boven te
|
||||
zien. Zie docs/Adverteren.md. *@
|
||||
@if (Reclame is not null)
|
||||
{
|
||||
<a class="advertentie" href="/advertentie/@Reclame.Id/uit"
|
||||
target="_blank" rel="noopener noreferrer nofollow">
|
||||
@if (Reclame.HeeftAfbeelding)
|
||||
{
|
||||
<img src="/advertentie/@Reclame.Id/afbeelding" alt="" />
|
||||
}
|
||||
<span class="groei">
|
||||
<span class="merkje">Advertentie</span>
|
||||
<span class="tekst">@Reclame.Tekst</span>
|
||||
</span>
|
||||
</a>
|
||||
}
|
||||
|
||||
<div class="raster twee">
|
||||
<a class="kaart klikbaar" href="/kluis">
|
||||
<span class="groot">Mijn kluis <span class="aantal">@(Gegevens?.AantalKluis ?? 0)</span></span>
|
||||
</a>
|
||||
|
||||
<a class="kaart klikbaar" href="/familie">
|
||||
<span class="groot">Mijn mensen <span class="aantal">@(Gegevens?.AantalFamilie ?? 0)</span></span>
|
||||
</a>
|
||||
|
||||
@* Twee richtingen, dus twee aantallen; die staan achter de titel in hetzelfde
|
||||
rondje als de andere tegels, met hun naam erbij zodat je niet hoeft te raden
|
||||
welke welke is. Zo past de tegel op één regel, even hoog als de andere drie. *@
|
||||
<a class="kaart klikbaar" href="/momenten">
|
||||
<span class="groot">
|
||||
Momenten
|
||||
<span class="aantal" title="@(Gegevens?.AantalVoorMij ?? 0) voor mij, @(Gegevens?.AantalVanMij ?? 0) van mij">
|
||||
↓@(Gegevens?.AantalVoorMij ?? 0) · ↑@(Gegevens?.AantalVanMij ?? 0)
|
||||
</span>
|
||||
@if (Gegevens is { AantalNieuweBerichten: > 0 })
|
||||
{
|
||||
<span class="aantal nieuw">@Gegevens.AantalNieuweBerichten</span>
|
||||
}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a class="kaart klikbaar" href="/nalatenschap">
|
||||
<span class="groot">Nalatenschap <span class="aantal">@(Gegevens?.AantalBeheerders ?? 0)</span></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if (Gegevens is not null)
|
||||
{
|
||||
<details class="uitklap" style="margin-top:1.5rem">
|
||||
<summary>Hoe ver vooruit wil je kijken?</summary>
|
||||
<p>
|
||||
Hierboven zie je wat er de komende tijd voor je klaarstaat. Zet het op 0 als je
|
||||
liever verrast wordt.
|
||||
</p>
|
||||
<div class="rij">
|
||||
<select @bind="Dagen" @bind:after="VooruitblikOpslaan" style="max-width:14rem">
|
||||
<option value="0">Niets vooruit tonen</option>
|
||||
<option value="7">7 dagen</option>
|
||||
<option value="14">14 dagen</option>
|
||||
<option value="30">30 dagen</option>
|
||||
<option value="60">60 dagen</option>
|
||||
</select>
|
||||
</div>
|
||||
</details>
|
||||
}
|
||||
|
||||
@* Dezelfde uitleg als in de app en op de pagina /watismijnbesluit, maar hier als popup:
|
||||
je hoeft dan niet weg van je overzicht en weer terug.
|
||||
|
||||
De privacyverklaring staat er om dezelfde reden bij, en op dezelfde plek als in de app.
|
||||
Er is ook een pagina /privacy - die is er voor wie hem los wil kunnen delen en voor
|
||||
Google Play, dat een adres wil dat je kunt aanklikken. Maar wie hier zit, hoort hem te
|
||||
kunnen lezen zonder zijn overzicht kwijt te raken. De tekst zelf staat in
|
||||
Privacytekst.razor, hetzelfde onderdeel dat /privacy en de app gebruiken. *@
|
||||
<p style="margin-top:1rem">
|
||||
<button type="button" class="alsLink" @onclick="() => Uitleg = true">Wat is MijnBesluit?</button>
|
||||
<br />
|
||||
<button type="button" class="alsLink" @onclick="() => Privacy = true">Privacyverklaring</button>
|
||||
<br />
|
||||
<button type="button" class="alsLink" @onclick="() => VersiehistorieOpen = true">Versiehistorie</button>
|
||||
</p>
|
||||
|
||||
@if (Uitleg)
|
||||
{
|
||||
<Popup Titel="Wat is MijnBesluit?" Bevestigtekst="Sluiten" AlleenSluiten="true"
|
||||
OpBevestigen="() => Uitleg = false" OpSluiten="() => Uitleg = false">
|
||||
<Productuitleg />
|
||||
</Popup>
|
||||
}
|
||||
|
||||
@if (Privacy)
|
||||
{
|
||||
<Popup Titel="Privacy" Bevestigtekst="Sluiten" AlleenSluiten="true"
|
||||
OpBevestigen="() => Privacy = false" OpSluiten="() => Privacy = false">
|
||||
<Privacytekst />
|
||||
</Popup>
|
||||
}
|
||||
|
||||
@* Zelfde tekst als in de app: Versiehistorie.razor staat twee keer op schijf en een
|
||||
zelfcontrole vergelijkt ze letterlijk. *@
|
||||
@if (VersiehistorieOpen)
|
||||
{
|
||||
<Popup Titel="Versiehistorie" Bevestigtekst="Sluiten" AlleenSluiten="true"
|
||||
OpBevestigen="() => VersiehistorieOpen = false" OpSluiten="() => VersiehistorieOpen = false">
|
||||
<Versiehistorie />
|
||||
</Popup>
|
||||
}
|
||||
|
||||
<div class="kaart">
|
||||
<h2>Waar is MijnBesluit voor?</h2>
|
||||
<p class="zacht" style="margin-bottom:.8rem">
|
||||
Voor alles wat je zou willen doorgeven maar wat nu alleen in jouw hoofd zit.
|
||||
</p>
|
||||
<ul class="zacht" style="padding-left:1.2rem;margin:0">
|
||||
<li>
|
||||
<strong>Je kluis</strong> — wachtwoorden, de pincode van je telefoon,
|
||||
polissen, documenten, je uitvaartwensen. Alles versleuteld, en jij bepaalt per
|
||||
onderdeel of het alleen voor jou is, pas na je overlijden vrijkomt, of op een
|
||||
datum die je zelf kiest.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Je mensen</strong> — familie en vrienden die je toevoegt en
|
||||
uitnodigt. Zolang iemand de uitnodiging niet heeft aangenomen, beheer jij dat
|
||||
profiel; daarna is het van hem of haar.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Momenten</strong> — een tekst- of videobericht dat je klaarzet
|
||||
voor iemand. Te bezorgen op een datum die jij kiest, of pas na je overlijden.
|
||||
Een verjaardag die je niet meer meemaakt, of gewoon iets wat je nog wilt zeggen.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Je nalatenschap</strong> — wie er straks mag regelen wat er
|
||||
geregeld moet worden. Die persoon krijgt pas toegang als je overlijden is
|
||||
bevestigd door meerdere mensen én jij er zelf niet op hebt gereageerd.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Authorized>
|
||||
</AuthorizeView>
|
||||
|
||||
@code {
|
||||
[CascadingParameter] private Task<AuthenticationState>? AuthState { get; set; }
|
||||
|
||||
private long _gebruikerId, _persoonId;
|
||||
private Overzicht? Gegevens;
|
||||
private int Dagen = 30;
|
||||
|
||||
/// <summary>Profielen die anderen op mijn adres hebben aangemaakt; alleen ik kan zeggen of ik dat ben.</summary>
|
||||
private IReadOnlyList<AccountService.Aantekeningaanbod> Aantekeningen =
|
||||
Array.Empty<AccountService.Aantekeningaanbod>();
|
||||
|
||||
/// <summary>Staat de uitleg open?</summary>
|
||||
private bool Uitleg;
|
||||
|
||||
/// <summary>Staat de privacyverklaring open?</summary>
|
||||
private bool Privacy;
|
||||
private bool VersiehistorieOpen;
|
||||
|
||||
/// <summary>De advertentie voor deze keer, of null als er geen is.</summary>
|
||||
private Campagne? Reclame;
|
||||
private bool Bezig;
|
||||
private string? Fout, Melding;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (AuthState is null) return;
|
||||
var user = (await AuthState).User;
|
||||
_gebruikerId = user.UserId() ?? 0;
|
||||
_persoonId = user.PersonId() ?? 0;
|
||||
|
||||
await Laden();
|
||||
}
|
||||
|
||||
private async Task Laden()
|
||||
{
|
||||
if (_gebruikerId == 0) return;
|
||||
|
||||
var uitkomst = await Overzichten.VoorAsync(_gebruikerId);
|
||||
if (!uitkomst.Succeeded) { Fout = uitkomst.Error; return; }
|
||||
|
||||
Fout = null;
|
||||
Gegevens = uitkomst.Value;
|
||||
Dagen = Gegevens!.VooruitblikDagen;
|
||||
|
||||
// De keuze en het tellen horen bij elkaar: wat hier wordt uitgekozen komt ook echt in
|
||||
// beeld. Eén advertentie per keer dat het overzicht wordt geopend; zie docs/Adverteren.md.
|
||||
//
|
||||
// Gaat er hier iets mis, dan hoort het overzicht er gewoon te staan. Reclame is het
|
||||
// minst belangrijke op dit scherm.
|
||||
try
|
||||
{
|
||||
Reclame = await Adverteren.KiesAsync();
|
||||
if (Reclame is not null) await Adverteren.TelVertoningAsync(Reclame.Id);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Reclame = null;
|
||||
}
|
||||
|
||||
// Heeft iemand een profiel voor mij aangemaakt? Apart opgehaald, en een fout hier hoort
|
||||
// het overzicht niet weg te houden: dit is een vraag die best een keer later mag komen.
|
||||
try { Aantekeningen = await Accounts.AantekeningenOverMijAsync(_gebruikerId); }
|
||||
catch (Exception) { Aantekeningen = Array.Empty<AccountService.Aantekeningaanbod>(); }
|
||||
}
|
||||
|
||||
/// <summary>"Ja, dat ben ik." Daarna staat alles wat die ander over je had bij jou.</summary>
|
||||
private async Task Overnemen(long persoonId)
|
||||
{
|
||||
Bezig = true;
|
||||
try
|
||||
{
|
||||
var uitkomst = await Accounts.NeemAantekeningOverAsync(persoonId, _gebruikerId, Samenvoegen);
|
||||
Fout = uitkomst.Succeeded ? null : uitkomst.Error;
|
||||
Melding = uitkomst.Succeeded ? "Klaar. Het profiel staat nu bij jou." : null;
|
||||
if (uitkomst.Succeeded) await Laden();
|
||||
}
|
||||
finally { Bezig = false; }
|
||||
}
|
||||
|
||||
/// <summary>"Nee, dat ben ik niet." De vraag komt niet terug.</summary>
|
||||
private async Task Afwijzen(long persoonId)
|
||||
{
|
||||
Bezig = true;
|
||||
try
|
||||
{
|
||||
var uitkomst = await Accounts.WijsAantekeningAfAsync(persoonId, _gebruikerId);
|
||||
Fout = uitkomst.Succeeded ? null : uitkomst.Error;
|
||||
if (uitkomst.Succeeded)
|
||||
Aantekeningen = Aantekeningen.Where(a => a.PersoonId != persoonId).ToList();
|
||||
}
|
||||
finally { Bezig = false; }
|
||||
}
|
||||
|
||||
private async Task VooruitblikOpslaan()
|
||||
{
|
||||
Bezig = true;
|
||||
try
|
||||
{
|
||||
var uitkomst = await Overzichten.VooruitblikAsync(_gebruikerId, Dagen);
|
||||
if (!uitkomst.Succeeded) { Fout = uitkomst.Error; return; }
|
||||
await Laden();
|
||||
}
|
||||
finally { Bezig = false; }
|
||||
}
|
||||
|
||||
private async Task IkBenErNog()
|
||||
{
|
||||
Bezig = true;
|
||||
try
|
||||
{
|
||||
var uitkomst = await NalatenschapService.ObjectAsync(_persoonId, _gebruikerId);
|
||||
Melding = uitkomst.Succeeded ? "Genoteerd. De melding is ingetrokken." : null;
|
||||
Fout = uitkomst.Succeeded ? null : uitkomst.Error;
|
||||
if (uitkomst.Succeeded) await Laden();
|
||||
}
|
||||
finally { Bezig = false; }
|
||||
}
|
||||
|
||||
private static string Teken(string soort) => soort switch
|
||||
{
|
||||
"beheerder" => "\U0001F33F", // blad: iemand beheert jouw nalatenschap
|
||||
"beheer-voor" => "\U0001F91D", // handdruk: jij beheert die van een ander
|
||||
"moment" => "✉", // envelop
|
||||
"overlijden" => "⚠", // waarschuwing
|
||||
_ => "•"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// "Dag Jonathan" als we de naam kennen, anders alleen "Welkom". Nooit het e-mailadres:
|
||||
/// dat is geen naam, en het staat raar boven een scherm over je nalatenschap.
|
||||
/// </summary>
|
||||
private static string Begroeting(string naam)
|
||||
{
|
||||
var voornaam = naam.Split(' ', StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
|
||||
return string.IsNullOrWhiteSpace(voornaam) ? "Welkom" : $"Dag {voornaam}";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user