Skip to content

Fase 1a: Platformkern

Fase 1a bouwt de gedeelde basis die alle diensten nodig hebben: klant-onboarding, hondprofielen met vaccinaties, het complete facturatiesysteem, online betalen via Sentoo, emailnotificaties en het basisbeheer voor admins. Na deze fase kan de eerste dienst (trainingen, Fase 1b) live.


Route: /onboarding

De onboarding is verplicht voor elke nieuwe klant. Zolang onboarding_completed = false is, wordt de klant bij elke login hierheen gestuurd. De flow bestaat uit drie stappen met een voortgangsbalk bovenaan.

Wat de gebruiker ziet:

Een formulier met persoonlijke gegevens en noodcontact.

VeldTypeVerplichtOpmerkingen
VoornaamtextJa
AchternaamtextJa
TelefoonnummertelJa
WhatsApp nummertelNeeVaak hetzelfde als telefoon
AdrestextJa
StadtextJa
Noodcontact naamtextJa
Noodcontact telefoontelJa
NotitiestextareaNeeVrij tekstveld

Onderaan: knop “Volgende” om naar stap 2 te gaan.

Wat er gebeurt:

  1. Client-side validatie met Zod. Verplichte velden worden gecontroleerd, telefoonnummers op geldig formaat.
  2. Bij “Volgende”: de gegevens worden opgeslagen via PATCH /api/clients/:id. De klant kan later terugkomen en verder gaan.
  3. Bij succesvolle opslag: doorsturen naar stap 2.

Foutmeldingen:

Inline per veld, bijvoorbeeld “Voornaam is verplicht” of “Voer een geldig telefoonnummer in.”

Wat de gebruiker ziet:

Een uitgebreid formulier om de eerste hond toe te voegen. De velden zijn gegroepeerd in secties.

Basisgegevens:

VeldTypeVerplicht
NaamtextJa
RastextJa
GeboortedatumdateJa
Geslachtselect (Reu/Teef)Ja
Gesteriliseerd/gecastreerdcheckboxNee
Gewicht (kg)numberJa
KleurtextJa
MicrochipnummertextNee
Hondenpaspoort nummertextNee
Fotofile uploadNee

Dierenarts:

VeldTypeVerplicht
Naam dierenartstextJa
Naam kliniektextNee
TelefoonnummertelJa

Voeding:

VeldTypeVerplicht
VoedingsmerktextJa
HoeveelheidtextJa
TijdentextJa
BijzonderhedentextareaNee

Medisch:

VeldTypeVerplicht
Medische aandoeningentextareaNee
MedicijnentextareaNee
AllergieentextareaNee
VerzekerdcheckboxNee

Gedrag:

VeldTypeVerplicht
GedragsnotitiestextareaNee

Een vrij tekstveld waar de klant beschrijft hoe de hond zich gedraagt met andere honden, met mensen en eventuele bijzondere aandachtspunten.

Vaccinaties:

Per vaccin (DHLPP, Bordetella, Rabies):

VeldTypeVerplicht
Datum toegedienddateJa (per vaccin)
VervaldatumdateJa
Documentfile uploadJa

De vaccinaties worden opgeslagen met verified_by_admin = false. Een admin moet ze later goedkeuren.

Nog een hond toevoegen:

Onderaan het formulier staat een knop “Nog een hond toevoegen”. Hiermee verschijnt hetzelfde formulier opnieuw, leeg, voor de volgende hond. Er is geen limiet in de app, maar het papieren formulier ondersteunt max 3 honden in de onboarding.

Knoppen: “Vorige” (terug naar stap 1), “Volgende” (naar stap 3).

Wat er gebeurt:

  1. Bij “Volgende”: POST /api/dogs per hond met alle gegevens. Vaccinatiedocumenten worden geupload naar Supabase Storage.
  2. Per vaccinatie: POST /api/vaccinations met datum, vervaldatum en bestandsreferentie.

Wat de gebruiker ziet:

  • Een scrollbaar tekstvak met de algemene voorwaarden en huisregels van Dog Hotel Aruba.
  • Een scrollbaar tekstvak met de aansprakelijkheidsverklaring.
  • Checkbox: “Ik heb de algemene voorwaarden en huisregels gelezen en ga hiermee akkoord.”
  • Knop “Afronden”

De checkbox is verplicht. Zonder akkoord kan de onboarding niet worden afgerond.

Wat er gebeurt:

  1. Bij “Afronden”: PATCH /api/clients/:id met terms_accepted_at = now() en onboarding_completed = true.
  2. Er wordt een welkomstmail verstuurd via Resend.
  3. Redirect naar /dashboard.

Foutmeldingen:

SituatieMelding
Checkbox niet aangevinkt”Je moet akkoord gaan met de voorwaarden om verder te gaan.”
Server error”Er ging iets mis bij het opslaan. Probeer het opnieuw.”

Route: /dogs/new

Hetzelfde formulier als stap 2 van de onboarding, maar dan als losse pagina. De klant kan na de onboarding extra honden toevoegen.

  1. Client-side validatie.
  2. POST /api/dogs met alle gegevens.
  3. Vaccinaties worden apart opgeslagen via POST /api/vaccinations.
  4. Na succes: redirect naar /dogs met een succesmelding “Hond toegevoegd.”

Dezelfde inline validatie als bij de onboarding. Bij een serverfout: “Er ging iets mis. Probeer het opnieuw.”


Wat de gebruiker ziet:

Een lijst van alle honden van de klant. Per hond een kaart met:

  • Foto (of placeholder als er geen foto is)
  • Naam
  • Ras
  • Leeftijd (berekend uit geboortedatum)
  • Vaccinatiestatus-indicator: geldig (groen), bijna verlopen (oranje, binnen 30 dagen), verlopen (rood)

Bovenaan: knop “Hond toevoegen” die naar /dogs/new gaat.

Wat de gebruiker ziet:

Het volledige hondprofiel in readonly modus:

  • Alle profielgegevens gegroepeerd (basis, dierenarts, voeding, medisch, gedrag)
  • Vaccinaties: een lijst per vaccin met status, datum, vervaldatum en eventueel het geuploade document
  • Upload-knop om een nieuw vaccinatiebewijs toe te voegen
  • Bezoekhistorie: de laatste 5 boekingen van deze hond
  • Knop “Bewerken” die naar /dogs/[id]/edit gaat

Vaccinatiebewijs uploaden:

  1. Klant klikt op “Vaccinatie uploaden” bij het betreffende vaccin.
  2. Er opent een modal of inline formulier met: datum, vervaldatum, document upload.
  3. Bij opslaan: POST /api/vaccinations met verified_by_admin = false.
  4. De vaccinatie verschijnt in de lijst met status “In afwachting van goedkeuring”.

Wat de gebruiker ziet:

Hetzelfde formulier als bij het toevoegen van een hond, maar voorgevuld met de bestaande gegevens.

Wat er gebeurt:

  1. Bij opslaan: PATCH /api/dogs/:id met de gewijzigde velden.
  2. Na succes: redirect naar /dogs/[id] met succesmelding.

Route: /dashboard

Een overzichtspagina met vier blokken:

Aankomende boekingen (max 3):

  • Per boeking: hond(en), dienst, datum, status
  • Als er geen boekingen zijn: “Geen aankomende boekingen” met een link naar “Nieuwe boeking”

Openstaande facturen:

  • Per factuur: factuurnummer, bedrag, status
  • Als er openstaande facturen zijn: totaalbedrag bovenaan
  • Link “Alle facturen” naar /invoices

Vaccinatiestatus:

  • Honden met verlopen of bijna verlopen vaccinaties
  • Per hond: naam + welk vaccin aandacht nodig heeft
  • Link naar het betreffende hondprofiel

Snelkoppelingen:

  • Knop “Nieuwe boeking” naar /bookings/new
  • Knop “Facturen betalen” naar /invoices (gefilterd op openstaand)

Wat de gebruiker ziet:

Een lijst met alle facturen, filterbaar op status.

Filters (tabs of dropdown):

  • Alle
  • Openstaand
  • Betaald
  • Verlopen

Bovenaan bij “Openstaand”: het totaal openstaande bedrag.

Per factuur in de lijst:

  • Factuurnummer (format: jaarXXXXXX)
  • Datum
  • Bedrag (incl. BBO en BAZV)
  • Status-badge: openstaand (geel), betaald (groen), verlopen (rood)

Klikken op een factuur opent de detailpagina.

Wat de gebruiker ziet:

De volledige factuur:

  • Factuurnummer, factuurdatum, vervaldatum
  • Gegevens Dog Hotel Aruba (naam, adres, bankgegevens)
  • Klantgegevens
  • Factuurregels: per hond per dienst een regel met beschrijving, eenheid, aantal, bedrag
  • Subtotaal
  • BBO (6%) en BAZV (1.5%) apart uitgesplitst
  • Totaalbedrag
  • Betaalstatus

Als de factuur openstaand is:

  • Knop “Betalen” die de Sentoo betaalflow start (zie sectie 6)
  • Knop “PDF downloaden”

Als de factuur betaald is:

  • Alleen “PDF downloaden”

Deze flow start wanneer een klant klikt op “Betalen” bij een openstaande factuur, of wanneer een betaallink per email is ontvangen.

  1. Klant klikt op “Betalen” in het portaal of opent de betaallink uit de email.

  2. De app maakt een Sentoo transactie aan: POST /api/invoices/:id/pay. De API roept Sentoo aan met bedrag, beschrijving en vervaldatum. Sentoo retourneert een payment_url en QR code.

  3. De klant ziet een tussenpagina met:

    • Het te betalen bedrag
    • Een QR code (voor mobiel bankieren)
    • Een knop “Ga naar betalen” die doorlinkt naar de Sentoo betaalpagina
  4. Op de Sentoo tussenpagina kiest de klant zijn bank: Aruba Bank, CMB, Banco di Caribe, etc.

  5. De klant wordt doorgestuurd naar zijn eigen bankapp en autoriseert de betaling met PIN, vingerafdruk of token.

  6. Na betaling stuurt Sentoo een webhook naar POST /api/payments/webhook:

    • De API verifieert de x-sentoo-signature header.
    • De API checkt of de factuur niet al betaald is (idempotent).
    • De factuurstatus wordt bijgewerkt naar “betaald”.
    • Er wordt een bevestigingsmail gestuurd naar de klant.
  7. De klant keert terug naar het portaal en ziet de factuur als “Betaald”.

SituatieWat er gebeurt
Betaling mislukt bij de bankSentoo stuurt status failed. De klant krijgt een melding en kan opnieuw proberen.
Betaallink verlopenDe klant ziet “Deze betaallink is verlopen.” Er kan een nieuwe link worden aangemaakt.
Klant sluit browser tijdens betalingDe webhook komt alsnog binnen als de betaling is gelukt. De factuurstatus wordt bijgewerkt.
Dubbele webhookDe API is idempotent: als de factuur al betaald is, wordt de webhook genegeerd.

Wat de admin ziet:

  • Zoekbalk bovenaan: zoeken op naam, email of telefoonnummer.
  • Een tabel met alle klanten:
KolomOmschrijving
NaamVoor- en achternaam
HondenAantal honden (of namen)
Laatste boekingDatum van de meest recente boeking
StatusAccountstatus (actief, onboarding niet voltooid)
  • Knop “Klant toevoegen” (deze functionaliteit komt in Fase 2, knop is zichtbaar maar nog niet actief).

Wat de admin ziet:

Een uitgebreid klantprofiel met meerdere secties:

Persoonsgegevens:

  • Alle gegevens uit de onboarding, bewerkbaar via een “Bewerken” knop die de velden editeerbaar maakt.

Honden:

  • Lijst van alle honden van deze klant met vaccinatiestatus.
  • Klikken op een hond opent /admin/dogs/[id].

Boekingshistorie:

  • Lijst van alle boekingen, gesorteerd op datum (nieuwste eerst).
  • Status per boeking.

Factuuroverzicht:

  • Alle facturen met betaalstatus.
  • Totaal openstaand.

Wat er gebeurt bij bewerken:

  1. Admin wijzigt gegevens en klikt “Opslaan”.
  2. PATCH /api/admin/clients/:id met de gewijzigde velden.
  3. Succesmelding bij de klantgegevens.

Wat de admin ziet:

  • Zoekbalk: zoeken op hondnaam of eigenaar.
  • Filter: vaccinatie verlopen, bijna verlopen, alles.
  • Tabel:
KolomOmschrijving
NaamNaam van de hond
RasRas
EigenaarNaam van de klant
VaccinatiestatusGeldig / bijna verlopen / verlopen

Wat de admin ziet:

Het volledige hondprofiel, vergelijkbaar met wat de klant ziet maar met extra mogelijkheden:

Profielgegevens:

  • Alle velden zijn bewerkbaar.
  • Extra veld: “Bijzonderheden” (special_notes), een tekstveld voor terugkerende aandachtspunten die bij de volgende check-in worden getoond.

Vaccinaties beheren:

  • Lijst van alle vaccinaties met status.
  • Per vaccinatie: goedkeuren of afkeuren. De klant uploadt vaccinatiebewijzen met verified_by_admin = false. De admin reviewt het document en kan op “Goedkeuren” klikken.
  • Knop “Vaccinatie toevoegen” voor handmatig toevoegen (als de klant het bewijs fysiek heeft meegenomen).

Boekingshistorie:

  • Alle boekingen van deze hond.

Wat er gebeurt bij goedkeuren vaccinatie:

  1. Admin klikt “Goedkeuren” bij een vaccinatie.
  2. PATCH /api/admin/vaccinations/:id met verified_by_admin = true.
  3. De vaccinatiestatus wordt direct bijgewerkt in de UI.

Wat de admin ziet:

  • Filters: openstaand, betaald, verlopen.
  • Totaalbedragen per filter bovenaan.
  • Tabel:
KolomOmschrijving
FactuurnummerFormat jaarXXXXXX
KlantNaam van de klant
DatumFactuurdatum
BedragTotaalbedrag incl. belasting
StatusOpenstaand / betaald / verlopen
  • Knop “PDF genereren” per factuur.
  • Export als CSV (voor de boekhouder).

Wat de admin ziet:

De volledige factuur zoals de klant die ziet, plus extra acties:

Factuurgegevens:

  • Gespecificeerd per hond per dienst.
  • BBO (6%) en BAZV (1.5%) apart.
  • Bankgegevens Dog Hotel Aruba.

Acties:

ActieWanneer beschikbaarWat er gebeurt
Handmatig markeren als betaaldFactuur is openstaandModal: kies betaalmethode (Cash / PIN), bevestig bedrag. PATCH /api/admin/invoices/:id/mark-paid met methode, tijdstip, medewerker-ID.
Herinnering sturenFactuur is openstaand of verlopenStuurt een herinneringsmail naar de klant met betaallink.
PDF genererenAltijdGenereert een PDF via Forme PDF (Rust/WASM op CF Workers) en opent een download.

Handmatig betaald markeren:

  1. Admin klikt “Markeer als betaald”.
  2. Modal verschijnt: kies Cash of PIN.
  3. Het bedrag wordt getoond ter bevestiging.
  4. Bij bevestigen: de factuur wordt als betaald gemarkeerd met de methode, het tijdstip en wie het heeft geregistreerd.
  5. De klant ontvangt een bevestigingsmail.

Route: /admin/settings

De instellingenpagina is opgedeeld in tabs of secties.

Wat de admin ziet:

  • Tabel met alle diensten: naam, type (single/bundle/subscription), prijs, eenheid, actief/inactief.
  • Toggle om een dienst actief of inactief te maken.
  • Knop “Dienst bewerken” per rij.
  • Knop “Nieuwe dienst” bovenaan.

Dienst bewerken:

  • Naam, beschrijving.
  • Prijs en eenheid (per dag, per nacht, per les, per maand).
  • Type: single, bundle of subscription.
  • Actief/inactief toggle.

Wat er gebeurt:

  • PATCH /api/admin/services/:id of POST /api/admin/services.
  • Prijswijzigingen gelden alleen voor nieuwe boekingen. Bestaande boekingen houden de snapshot-prijs.

Wat de admin ziet:

  • Hotelnaam
  • Logo (upload)
  • Adres
  • Telefoonnummer
  • Email

Deze gegevens worden getoond op facturen en in emails.

Wat er gebeurt:

  • PATCH /api/admin/settings met de gewijzigde velden.
  • Het logo wordt geupload naar Supabase Storage.

Wat de admin ziet:

  • Lijst van alle medewerkers met naam, email en rol.
  • Knop “Medewerker toevoegen”.
  • Per medewerker: bewerken of deactiveren.

Medewerker toevoegen:

  1. Admin vult naam, email en rol (admin / medewerker / trainer) in.
  2. POST /api/admin/users maakt een account aan.
  3. De medewerker ontvangt een uitnodigingsmail met een link om een wachtwoord in te stellen.

Rollen:

  • admin: volledige toegang tot alle admin functies.
  • medewerker: toegang tot dagelijkse operatie (boekingen, check-in/out, honden, klanten). Geen toegang tot instellingen en financieel overzicht.
  • trainer: kan lessen inplannen en notities toevoegen bij trainingen.

Route: /account

Een pagina met drie secties:

Persoonlijke gegevens:

  • Dezelfde velden als stap 1 van de onboarding, voorgevuld.
  • Knop “Opslaan” om wijzigingen door te voeren.

Wachtwoord wijzigen:

  • Veld “Huidig wachtwoord”
  • Veld “Nieuw wachtwoord” (min. 8 karakters)
  • Veld “Bevestig nieuw wachtwoord”
  • Knop “Wachtwoord wijzigen”

Taalvoorkeur:

  • Keuze tussen NL en EN.
  • Wordt direct opgeslagen en toegepast.

Gegevens bewerken:

  1. Klant wijzigt velden en klikt “Opslaan”.
  2. PATCH /api/clients/:id.
  3. Succesmelding “Gegevens opgeslagen.”

Wachtwoord wijzigen:

  1. supabase.auth.updateUser({ password }) na verificatie van het huidige wachtwoord.
  2. Succesmelding “Wachtwoord gewijzigd.”

Foutmeldingen:

SituatieMelding
Huidig wachtwoord onjuist”Het huidige wachtwoord is onjuist.”
Nieuwe wachtwoorden komen niet overeen”Wachtwoorden komen niet overeen.”
Nieuw wachtwoord te kort”Wachtwoord moet minimaal 8 karakters zijn.”

Fase 1a introduceert de eerste emailnotificaties. Ze worden verstuurd via Resend met React Email templates, in de voorkeurstaal van de gebruiker (NL of EN).

TriggerOntvangerInhoud
Registratie voltooidKlantWelkomstmail met link naar het portaal
Boeking bevestigdKlantBoekingsdetails, datum, hond(en), betaallink
Betaling ontvangenKlantBevestiging met factuurnummer en bedrag
Nieuwe boekingsaanvraagAdminMelding dat er een nieuwe aanvraag is met link naar de boeking