Eerste commit
This commit is contained in:
@@ -0,0 +1,352 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace MijnBesluit.Client;
|
||||
|
||||
// De vorm van wat de SocketServer terugstuurt. De namen komen overeen met wat de dispatcher
|
||||
// verstuurt; het protocol gebruikt kleine beginletters, dat regelt de JSON-instelling.
|
||||
|
||||
public record SessieGegevens(
|
||||
[property: JsonPropertyName("token")] string Token,
|
||||
[property: JsonPropertyName("persoonId")] long PersoonId,
|
||||
[property: JsonPropertyName("verlooptOp")] DateTime? VerlooptOp);
|
||||
|
||||
public record CodeGestuurd(
|
||||
[property: JsonPropertyName("verstuurdNaar")] string VerstuurdNaar,
|
||||
[property: JsonPropertyName("geldigTot")] DateTime GeldigTot);
|
||||
|
||||
public record FamilieOverzicht(long Id, string Name, bool Eigenaar);
|
||||
|
||||
/// <summary>Eén regel op het beginscherm: iets wat speelt of eraan komt.</summary>
|
||||
public record Overzichtsregel(string Soort, string Tekst, DateTime? Datum, long? Id)
|
||||
{
|
||||
public bool IsWaarschuwing => Soort == "overlijden";
|
||||
public bool IsMoment => Soort == "moment";
|
||||
}
|
||||
|
||||
/// <summary>Alles wat het beginscherm laat zien.</summary>
|
||||
public record Overzicht(
|
||||
int AantalKluis,
|
||||
int AantalFamilie,
|
||||
int AantalVoorMij,
|
||||
int AantalVanMij,
|
||||
int AantalNieuweBerichten,
|
||||
int AantalBeheerders,
|
||||
int VooruitblikDagen,
|
||||
IReadOnlyList<Overzichtsregel> Regels);
|
||||
|
||||
/// <summary>
|
||||
/// De sociale media die je bij een kluisitem kunt kiezen.
|
||||
///
|
||||
/// Dit is een kopie van SocialeMedia in MijnBesluit.Domain: de app ziet het domein niet, want
|
||||
/// die praat alleen over de socket. Een controle in de zelftest bewaakt dat de twee lijsten
|
||||
/// gelijk blijven, zodat ze niet stilletjes uit elkaar lopen.
|
||||
/// </summary>
|
||||
public static class SocialeMedia
|
||||
{
|
||||
public const string Anders = "Anders";
|
||||
|
||||
public static readonly string[] Namen =
|
||||
{
|
||||
"Facebook", "Instagram", "WhatsApp", "LinkedIn", "X (voorheen Twitter)",
|
||||
"TikTok", "YouTube", "Snapchat", "Pinterest", "Telegram", "Signal",
|
||||
"Discord", "Reddit", "Strava", "Marktplaats", Anders
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Datums zoals ze op het scherm horen te staan, in het Nederlands.
|
||||
///
|
||||
/// Dit is een kopie van Datums in MijnBesluit.Domain: de app ziet het domein niet. Een controle
|
||||
/// in de zelftest bewaakt dat de twee gelijk blijven.
|
||||
///
|
||||
/// Waarom dit met de hand gaat en niet met ToString("d MMMM yyyy"): dat volgt de taalinstelling
|
||||
/// van het toestel, en dan leest een telefoon die op Engels staat "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.
|
||||
/// </summary>
|
||||
public static class Datums
|
||||
{
|
||||
public static readonly string[] Maanden =
|
||||
{
|
||||
"januari", "februari", "maart", "april", "mei", "juni",
|
||||
"juli", "augustus", "september", "oktober", "november", "december"
|
||||
};
|
||||
|
||||
/// <summary>Afkortingen voor waar het krap is. "Mei" heeft geen punt: dat is geen afkorting.</summary>
|
||||
public static readonly string[] KorteMaanden =
|
||||
{
|
||||
"Jan.", "Feb.", "Mrt.", "Apr.", "Mei", "Jun.",
|
||||
"Jul.", "Aug.", "Sep.", "Okt.", "Nov.", "Dec."
|
||||
};
|
||||
|
||||
/// <summary>Zondag eerst, want zo telt DayOfWeek.</summary>
|
||||
public static readonly string[] Dagen =
|
||||
{
|
||||
"zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wat iemand van je is: de lijst die je te kiezen krijgt, en hoe elke relatie heet.
|
||||
///
|
||||
/// Dit is een kopie van Relaties in MijnBesluit.Domain: de app ziet het domein niet, want die
|
||||
/// praat alleen over de socket. Daarom staan hier nummers en geen enum - dat is wat er over de
|
||||
/// lijn gaat. Een controle in de zelftest bewaakt dat de twee lijsten gelijk blijven.
|
||||
///
|
||||
/// <see cref="Keuzes"/> is wat je kunt kiezen, <see cref="Naam"/> vertaalt élke waarde die ooit
|
||||
/// heeft bestaan. Kind, Bonuskind, Ouder, Bonusouder, Kleinkind en Grootouder kun je niet meer
|
||||
/// kiezen, maar staan wel bij bestaande mensen in de database; zonder vertaling zou daar ineens
|
||||
/// niets meer staan.
|
||||
/// </summary>
|
||||
public static class Relaties
|
||||
{
|
||||
public static readonly (int Waarde, string Naam)[] Keuzes =
|
||||
{
|
||||
(1, "Partner"),
|
||||
|
||||
(11, "Zoon"),
|
||||
(12, "Dochter"),
|
||||
(28, "Bonuszoon"),
|
||||
(29, "Bonusdochter"),
|
||||
(16, "Schoonzoon"),
|
||||
(15, "Schoondochter"),
|
||||
|
||||
(14, "Kleinzoon"),
|
||||
(13, "Kleindochter"),
|
||||
(33, "Achterkleinzoon"),
|
||||
(32, "Achterkleindochter"),
|
||||
|
||||
(19, "Vader"),
|
||||
(20, "Moeder"),
|
||||
(22, "Bonusvader"),
|
||||
(21, "Bonusmoeder"),
|
||||
(24, "Schoonvader"),
|
||||
(25, "Schoonmoeder"),
|
||||
(17, "Opa"),
|
||||
(18, "Oma"),
|
||||
|
||||
(6, "Broer"),
|
||||
(7, "Zus"),
|
||||
(30, "Bonusbroer"),
|
||||
(31, "Bonuszus"),
|
||||
(26, "Zwager"),
|
||||
(27, "Schoonzus"),
|
||||
(34, "Oom"),
|
||||
(35, "Tante"),
|
||||
|
||||
(10, "Vriend"),
|
||||
(23, "Vriendin"),
|
||||
(99, "Anders")
|
||||
};
|
||||
|
||||
/// <summary>Hoe een relatie op het scherm heet - ook de relaties die je niet meer kunt kiezen.</summary>
|
||||
public static string Naam(int relatie) => relatie switch
|
||||
{
|
||||
2 => "Kind",
|
||||
3 => "Bonuskind",
|
||||
4 => "Ouder",
|
||||
5 => "Bonusouder",
|
||||
8 => "Kleinkind",
|
||||
9 => "Grootouder",
|
||||
0 => "Familie",
|
||||
_ => Keuzes.FirstOrDefault(k => k.Waarde == relatie).Naam ?? "Familie"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Een profiel dat iemand anders voor je heeft aangemaakt op jouw e-mailadres, en waarvan alleen
|
||||
/// jij kunt zeggen of het over jou gaat. Zie docs/Identiteit.md.
|
||||
/// </summary>
|
||||
public record Aantekening(long PersoonId, string Van, string? Relatie, DateTime AangemaaktOp);
|
||||
|
||||
/// <summary>Eigendomsstatus van een profiel: 0 beheerd, 1 uitgenodigd, 2 geclaimd.</summary>
|
||||
public enum ProfielStand { Beheerd = 0, Uitgenodigd = 1, Geclaimd = 2 }
|
||||
|
||||
public record Familielid(
|
||||
long PersonId,
|
||||
string DisplayName,
|
||||
string FirstName,
|
||||
string LastName,
|
||||
string? Email,
|
||||
int Relation,
|
||||
string? RelationLabel,
|
||||
ProfielStand State,
|
||||
bool CanEdit,
|
||||
DateOnly? BirthDate,
|
||||
DateOnly? DateOfDeath,
|
||||
|
||||
// De geschiedenis van het profiel. Komt rechtstreeks van de server; alles in UTC.
|
||||
DateTime CreatedAt,
|
||||
DateTime? InvitedAt,
|
||||
DateTime? InvitationExpiresAt,
|
||||
int InvitationResends,
|
||||
DateTime? ClaimedAt,
|
||||
|
||||
// Twee dingen die pas ter sprake komen als je iemand weghaalt, maar die meekomen met de
|
||||
// lijst zodat het scherm ze meteen heeft. Zie FamilyService.VerwijderLidAsync.
|
||||
bool IsBeheerder,
|
||||
int MomentenKlaar,
|
||||
|
||||
// De profielfoto. Het nummer om hem groot op te halen, en de kleine versie als base64 om
|
||||
// hem meteen te kunnen tonen zonder tweede ronde langs de server.
|
||||
long? ProfielfotoId = null,
|
||||
string? Profielfoto = null)
|
||||
{
|
||||
public bool IsGeclaimd => State == ProfielStand.Geclaimd;
|
||||
|
||||
/// <summary>De kleine profielfoto als verwijzing die een img-element rechtstreeks aankan.</summary>
|
||||
public string? Profielfotobron =>
|
||||
string.IsNullOrEmpty(Profielfoto) ? null : $"data:image/jpeg;base64,{Profielfoto}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wat er verdwijnt als je je account opheft. Staat in het scherm vóórdat iemand ja zegt:
|
||||
/// "weet je het zeker?" is een lege vraag, "je kluis met 23 items" is er een waar iemand echt
|
||||
/// over nadenkt.
|
||||
/// </summary>
|
||||
public record Opheffing(int Kluisitems, int Bestanden, int BerichtenKlaar, int BerichtenBezorgd,
|
||||
int Mensen, int Nalatenschappen);
|
||||
|
||||
/// <summary>Je eigen gegevens, zoals het profielscherm ze toont.</summary>
|
||||
public record EigenProfiel(long PersoonId, string Voornaam, string Achternaam, string Email,
|
||||
DateOnly? Geboortedatum, DateTime LidSinds,
|
||||
// De kleine versie van je eigen profielfoto, als base64. Die gaat mee
|
||||
// in dit antwoord omdat de app hem op meer schermen laat zien dan
|
||||
// alleen je profiel - in de kluis staat hij bij "Alleen voor mijzelf".
|
||||
// Een eigen ronde langs de server voor een plaatje van veertig pixels
|
||||
// zou duurder zijn dan het plaatje zelf.
|
||||
string? Profielfoto = null)
|
||||
{
|
||||
public string Naam => string.Join(" ",
|
||||
new[] { Voornaam, Achternaam }.Where(d => !string.IsNullOrWhiteSpace(d)));
|
||||
|
||||
/// <summary>De kleine profielfoto als verwijzing die een img-element rechtstreeks aankan.</summary>
|
||||
public string? Profielfotobron =>
|
||||
string.IsNullOrEmpty(Profielfoto) ? null : $"data:image/jpeg;base64,{Profielfoto}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Een nalatenschap die jij beheert. <see cref="Afgerond"/> is false zolang de persoon er
|
||||
/// gewoon is: dan weet je alleen dat je bent aangewezen en valt er niets in te zien.
|
||||
/// </summary>
|
||||
public record Toevertrouwd(long PersonId, string DisplayName, DateOnly? DateOfDeath,
|
||||
DateTime? AccessGrantedAt, int AantalItems,
|
||||
bool Afgerond = false, int Volgorde = 1, string? Profielfoto = null,
|
||||
int RequiredDeclarations = 3, int ObjectionDays = 14)
|
||||
{
|
||||
/// <summary>De kleine profielfoto als verwijzing die een img-element rechtstreeks aankan.</summary>
|
||||
public string? Profielfotobron =>
|
||||
string.IsNullOrEmpty(Profielfoto) ? null : $"data:image/jpeg;base64,{Profielfoto}";
|
||||
}
|
||||
|
||||
public record KluisItem(
|
||||
long Id,
|
||||
string Title,
|
||||
int Category,
|
||||
int ReleasePolicy,
|
||||
DateTime? ReleaseAt,
|
||||
DateTime UpdatedAt,
|
||||
long? SharedManagerPersonId = null);
|
||||
|
||||
/// <summary>De ontsleutelde inhoud van een kluisitem. Per soort is maar een deel gevuld.</summary>
|
||||
public class KluisInhoud
|
||||
{
|
||||
public string? Notes { get; set; }
|
||||
public string? Website { get; set; }
|
||||
public string? Username { get; set; }
|
||||
public string? Secret { get; set; }
|
||||
public string? Pincode { get; set; }
|
||||
public string? DeviceName { get; set; }
|
||||
public string? RecoveryCodes { get; set; }
|
||||
|
||||
/// <summary>Welk sociaal medium; een van SocialeMedia.Namen, of "Anders".</summary>
|
||||
public string? Platform { get; set; }
|
||||
/// <summary>Alleen gevuld als Platform "Anders" is.</summary>
|
||||
public string? PlatformAnders { get; set; }
|
||||
|
||||
public string? Insurer { get; set; }
|
||||
public string? PolicyNumber { get; set; }
|
||||
public string? ContactPhone { get; set; }
|
||||
public decimal? Amount { get; set; }
|
||||
public string? BurialOrCremation { get; set; }
|
||||
public string? Location { get; set; }
|
||||
public string? Music { get; set; }
|
||||
public string? Speakers { get; set; }
|
||||
public string? Wishes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>Een bijlage bij een kluisitem, zonder de inhoud zelf.</summary>
|
||||
public record Bijlage(long Id, string FileName, string ContentType, long SizeBytes, DateTime CreatedAt,
|
||||
bool IsProfilePhoto = false)
|
||||
{
|
||||
/// <summary>De grootte zoals je hem aan iemand laat zien: "1,4 MB".</summary>
|
||||
public string Grootte => SizeBytes >= 1024 * 1024
|
||||
? $"{SizeBytes / 1024d / 1024d:0.#} MB"
|
||||
: $"{Math.Max(1, SizeBytes / 1024)} kB";
|
||||
|
||||
public bool IsAfbeelding => ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase);
|
||||
public bool IsVideo => ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>Een opgehaald bestand, met de inhoud erbij.</summary>
|
||||
public record BestandInhoud(string Naam, string Soort, byte[] Inhoud);
|
||||
|
||||
public record Bericht(
|
||||
long Id,
|
||||
string Subject,
|
||||
int Kind,
|
||||
long FromPersonId,
|
||||
long ToPersonId,
|
||||
DateTime? DeliveredAt,
|
||||
DateTime? ReadAt,
|
||||
DateTime? DeliverAt,
|
||||
bool DeliverAfterDeath,
|
||||
int Status,
|
||||
long? VaultFileId)
|
||||
{
|
||||
public bool IsNieuw => Status == 2; // 2 = bezorgd, 3 = gelezen
|
||||
|
||||
/// <summary>0 tekst, 1 video, 2 audio, 3 document.</summary>
|
||||
public bool IsVideo => Kind == 1;
|
||||
|
||||
/// <summary>Zit er een opname of bijlage bij dit bericht?</summary>
|
||||
public bool HeeftBestand => VaultFileId is > 0;
|
||||
}
|
||||
|
||||
/// <summary>De uitkomst van een proefmelding: is hij verstuurd, en zo niet waarom niet.</summary>
|
||||
public record Proefmelding(bool Gelukt, string Uitleg);
|
||||
|
||||
/// <summary>Iemand die jouw nalatenschap mag beheren. Volgorde 1 is de eerste keus.</summary>
|
||||
/// <summary>
|
||||
/// De advertentie die nu op het overzicht mag staan. De adressen zijn volledig: de app weet niet
|
||||
/// waar de site staat en hoort dat ook niet zelf in elkaar te zetten.
|
||||
/// </summary>
|
||||
/// <param name="Link">
|
||||
/// Gaat naar de site en niet rechtstreeks naar de adverteerder. Daar wordt de klik geteld en
|
||||
/// vandaar wordt doorgestuurd; zo is er één plek waar dat gebeurt.
|
||||
/// </param>
|
||||
public record Advertentie(long Id, string Tekst, string? Afbeelding, string Link);
|
||||
|
||||
public record Beheerder(long PersonId, string DisplayName, int Priority, DateTime? AccessGrantedAt,
|
||||
string? Profielfoto = null)
|
||||
{
|
||||
public bool HeeftToegang => AccessGrantedAt is not null;
|
||||
|
||||
/// <summary>De kleine profielfoto als verwijzing die een img-element rechtstreeks aankan.</summary>
|
||||
public string? Profielfotobron =>
|
||||
string.IsNullOrEmpty(Profielfoto) ? null : $"data:image/jpeg;base64,{Profielfoto}";
|
||||
}
|
||||
|
||||
public record NalatenschapStand(
|
||||
int State,
|
||||
int ActiveDeclarations,
|
||||
int RequiredDeclarations,
|
||||
DateTime? ObjectionDeadline,
|
||||
int Missing,
|
||||
int ObjectionDays = 14,
|
||||
bool BeheerderHeeftGemeld = false,
|
||||
bool WachtOpBeheerder = false)
|
||||
{
|
||||
public bool LooptEenProcedure => State == 1;
|
||||
public bool IsBevestigd => State == 3;
|
||||
}
|
||||
Reference in New Issue
Block a user