Billing (Frontend)
UI-Architectuur & Design
De Billing-UI leeft binnen het Beheer-scherm en is opgebouwd rond een tabbed SectionCard. Activatie van een abonnement gebeurt op een eigen scherm, omdat die flow een Stripe Payment Element en een terugkomstroute via SetupIntent vereist.
BeheerScreenrendertBillingSectionals hoofdsectie. Hierin zitten de plan-status, pool-overzicht, betaalmethoden, factuurlijst en het tab-paneel.BillingTabsCardtoont vijf tabs: Atlas, Uitnodigingen, Reviews, Gebruik en Limiet. De tabs zijn lazy-mounted:visitedTabsvoorkomt dat ongeziene tabs hun fetches starten.ActiverenScreenis een eigen route en rendert het Stripe Payment Element. Op web direct via@stripe/stripe-js; op native via eenWebViewdie dezelfde HTML laadt en het resultaat viapostMessageterugstuurt naar de app.LimietTabPanelcombineert deSpendingLimitSettings,ReviewCapModalenChannelCapModalvoor het beheren van EUR-plafond, review-caps en notificatiedrempels.UsageBarCharttoont per kalendermaand een gestapelde balk met platformfee, individuele reviews, ward-reviews, SMS-overage en briefoverage. De jaartabbladen worden gevuld vanuitusage_yearsin de summary.
graph TD
A[BeheerScreen] --> B[BillingSection]
B --> C[ReadOnlyBanner]
B --> D[PoolUsageCard]
B --> E[PaymentMethodManager]
B --> F[InvoiceList]
B --> G[BillingTabsCard]
G --> G1[Atlas tab]
G --> G2[ChannelsTabPanel]
G --> G3[Reviews tab]
G --> G4[UsageBarChart]
G --> G5[LimietTabPanel]
G5 --> G5a[SpendingLimitSettings]
G5 --> G5b[ReviewCapModal]
G5 --> G5c[ChannelCapModal]
H[ActiverenScreen] --> H1[Stripe PaymentElement / WebView]
State & Data Flow
Billing-state is bewust niet globaal: elke tab haalt zijn eigen data via billingApi. De brondata is GET /api/billing/summary/, die in een enkele response de plan-status, pool, factuurperiode, channel-usage en jaaroverzicht bevat. Aanvullende endpoints leveren detaildata (atlas, usage per jaar, spending-limit, payment methods, invoices).
- Initial load:
BillingSectionhaalt summary op. De Atlas-, Uitnodigingen- en Limiet-tabs lazy-laden hun extra data zodra de gebruiker erheen klikt. - Activatie:
ActiverenScreenvraagt eerst eenSetupIntentop viaPOST /api/billing/payment-methods/setup-intent/, toont het Stripe Payment Element met dat client_secret, en submit het resultaat naarPOST /api/billing/activate/(samen metterms_acceptedenpayment_method_idofsetup_intent_id). - Polling vervalt: na een succesvolle
activate-call leest de frontend opnieuw/summary/voor de bijgewerkte plan_status. Stripe-webhooks updaten ondertussenBillingProfile/BillingPeriodop de backend zonder dat de UI hoeft te pollen. - Notice acknowledgements:
useBillingNoticeAcknowledgementshaalt de huidige acks op viaGET /api/billing/acknowledgements/en bevestigt een soort overschrijding viaPOSTmetack_type. Daarmee worden de in-app popups voor de huidige factuurperiode onderdrukt.
sequenceDiagram
participant UI as ActiverenScreen
participant BE as Backend
participant Stripe as Stripe API
participant WH as Stripe Webhook
UI->>BE: POST /api/billing/payment-methods/setup-intent/
BE->>Stripe: SetupIntent.create
Stripe-->>BE: client_secret
BE-->>UI: client_secret + publishable_key + billing_details
UI->>Stripe: Confirm SetupIntent (PaymentElement)
Stripe-->>UI: setup_intent.status=succeeded
UI->>BE: POST /api/billing/activate/ {setup_intent_id, terms_accepted}
BE->>Stripe: PaymentMethod.attach + Subscription.create
Stripe-->>BE: subscription_id (status active|trialing)
BE-->>UI: 200 OK {subscription_id}
Stripe-->>WH: customer.subscription.updated
WH->>BE: upsert BillingPeriod, plan_status=active
Navigatie & Routing
/beheer: hoofdscherm met Billing-sectie. De tab-keuze wordt overgenomen uit de query-parametertab(atlas,uitnodigingen,reviews,gebruik,limiet)./beheer/billing/activeren: Stripe-activatie. Bouwt eenWebViewop native, of laadt het Payment Element direct op web. Returnt naar de app via een sentinel-URL dieparseBillingReturnUrlinterpreteert./beheer/billing/done: post-activatie scherm voor de native return-flow.- Permission gating: alle billing-routes vereisen
settings.manage_billing.PermissionGateschermt UI af; backend dwingt het viaHasPermissionCodeaf. - Modals: bevestiging van plan-cancel, EUR-cap aanpassen, review-caps aanpassen en betaalmethode-acties gebruiken
AppModal(geenAlert.alert). Server-feedback gaat viauseToast().
Bestandsstructuur & Verantwoordelijkheden
app/beheer/billing/activeren.tsx: Expo Router-route dieActiverenScreenmount.app/beheer/billing/done.tsx: post-activatie redirect-route voor de native return-flow.src/features/beheer/components/BillingSection.tsx: hoofdcomponent dat plan-status, pool, betaalmethoden, facturen en het tabpaneel orkestreert.src/features/billing/screens/ActiverenScreen.tsx: Stripe-activatie scherm met Payment Element (web direct, native viaWebView).src/features/billing/api/billingApi.ts: REST-client voor alle/api/billing/-endpoints.src/features/billing/types/billing.ts: TypeScript-types voor summary, status, spending-limit, atlas, payment methods en acknowledgements.src/features/billing/constants.ts: prijs- en bundleconstanten (PLATFORM_PRICE,PLATFORM_INCLUDED_PATIENTS,INDIVIDUAL_PRICE,WARD_PRICE,BTW_RATE,ATLAS_ENTERPRISE_PRICE).src/features/billing/components/AddPaymentMethodModal.tsx: modal voor het toevoegen van een betaalmethode via SetupIntent.src/features/billing/components/PaymentMethodManager.tsx,PaymentMethodCard.tsx: lijst en kaartweergave van betaalmethoden.src/features/billing/components/InvoiceList.tsx: facturenlijst met PDF-link naar Stripe.src/features/billing/components/SpendingLimitSettings.tsx,LimietTabPanel.tsx,ReviewCapModal.tsx,ChannelCapModal.tsx: beheer van EUR-plafond, review-caps en notificatiedrempels.src/features/billing/components/PoolUsageCard.tsx: visualisatie van inbegrepen vs verbruikte patienten in de huidige factuurperiode.src/features/billing/components/ChannelsTabPanel.tsx: SMS- en briefverbruik plus overage-prognose.src/features/billing/components/TrialStatusCard.tsx: trial-overzicht met resterende dagen.src/features/billing/components/UsageBarChart.tsx: gestapelde maandgrafiek voor verbruik en kosten.src/features/billing/components/EditBillingInfoModal.tsx,EditBedrijfsgegevensModal.tsx: bewerken van factuur-e-mail, adres, KVK en bedrijfsgegevens.src/features/billing/components/AdresAutocomplete.tsx,KvkAutocomplete.tsx: zoekvelden voor adres (PDOK) en KVK-validatie.src/features/billing/components/ReadOnlyBanner.tsx: melding bij trial-expired, cancelled of readonly plan.src/features/billing/components/skeletons/: lokale skeletons voor de billing-secties.src/features/billing/hooks/useBillingNoticeAcknowledgements.ts: hook die acks ophaalt en muteert.src/features/billing/lib/handleBillingReturn.ts: parse- en saveroutines voor de Stripe return-URL op web en native.
Belangrijke bestanden
src/features/beheer/components/BillingSection.tsxsrc/features/billing/screens/ActiverenScreen.tsxsrc/features/billing/api/billingApi.tssrc/features/billing/components/LimietTabPanel.tsxsrc/features/billing/components/SpendingLimitSettings.tsxsrc/features/billing/types/billing.tssrc/features/billing/constants.ts