Trainingen
Rol: lid (inschrijven), trainer (aanmaken en bijwerken), eigenaar (volledig beheer inclusief verwijderen)
De Trainingen-tab toont alle geplande groepstrainingen. Leden kunnen zich inschrijven zolang er nog plaatsen beschikbaar zijn. Trainers beheren hun eigen sessies; de eigenaar heeft volledige CRUD-toegang.
Inschrijfflow
Kleurcodering beschikbaarheid
| Beschikbare plekken | Kleur | Betekenis |
|---|---|---|
| ≥ 3 | Groen (#2e8b76) | Voldoende ruimte |
| 1 – 2 | Goud (#c9a84c) | Bijna vol |
| 0 | Grijs (#9a9e98) | Vol — wachtlijst actief |
Terugkerende trainingen
Trainingen met isRecurring: true verschijnen als wekelijkse sessiekaarten, gegroepeerd op de weekdag (recurringDay). De kaart toont de dag, het tijdstip, het niveau en de trainer. Inschrijving werkt identiek aan eenmalige trainingen — elk trainingsrecord vertegenwoordigt één concrete sessie, ook al is het onderdeel van een terugkerend schema.
Niveauclassificatie
| Waarde | Doelgroep |
|---|---|
beginner | Starters, geen padelervaring vereist |
intermediate | Spelers met basisvaardigheden |
advanced | Gevorderde competitiespelers |
kids | Jeugdtraining (t/m ca. 14 jaar) |
competition | Competitietraining en matchvoorbereiding |
Datamodellen
Trainings
Trainingen aangemaakt door trainers of de eigenaar. Leden kunnen zich inschrijven.
| Veld | Type | Verplicht | Beschrijving | Beperkingen |
|---|---|---|---|---|
name | text | ✓ | Naam van de training | — |
description | text | — | Uitgebreide beschrijving | — |
date | date | ✓ | Datum van de training | — |
startTime | text | ✓ | Starttijd als HH:MM string | — |
endTime | text | ✓ | Eindtijd als HH:MM string | — |
court | text | ✓ | Baanidentificatie (bv. baan1) | — |
capacity | number | ✓ | Maximum aantal deelnemers | min 1 |
level | select | — | Niveau van de training | beginner | intermediate | advanced | kids | competition |
trainer | relation | — | Verantwoordelijke trainer | → users (max 1) |
isRecurring | bool | — | Geeft aan of de training wekelijks terugkeert | — |
recurringDay | select | — | Weekdag voor terugkerende trainingen | MA | DI | WO | DO | VR | ZA | ZO |
Toegangsregels
| Regel | Expressie |
|---|---|
list | @request.auth.id != '' |
view | @request.auth.id != '' |
create | @request.auth.role = 'trainer' || @request.auth.role = 'eigenaar' |
update | @request.auth.role = 'trainer' || @request.auth.role = 'eigenaar' |
delete | @request.auth.role = 'eigenaar' |
Inschrijvingen
Koppeltabel tussen leden en trainingen. Unieke index voorkomt dubbele inschrijvingen.
| Veld | Type | Verplicht | Beschrijving | Beperkingen |
|---|---|---|---|---|
training | relation | ✓ | Verwijzing naar de training | → trainings · cascade delete |
user | relation | ✓ | Ingeschreven gebruiker | → users |
enrolledAt | date | — | Tijdstip van inschrijving (server default) | — |
Indexen: UNIQUE (training, user) — voorkomt dubbele inschrijving
Toegangsregels
| Regel | Expressie |
|---|---|
list | @request.auth.id != '' |
view | @request.auth.id != '' |
create | @request.auth.id != '' |
update | @request.auth.id = user.id || @request.auth.role = 'eigenaar' |
delete | @request.auth.id = user.id || @request.auth.role = 'eigenaar' |
Ontwerpkeuzes
UNIQUE-index als veiligheidsnet
De combinatie (training, user) in training_enrollments heeft een UNIQUE-index in PocketBase. De app controleert aan de clientzijde al of een gebruiker ingeschreven is (knop op disabled), maar de index garandeert dat een race condition of dubbele aanroep nooit leidt tot een dubbele inschrijving in de database.
spotsLeft berekend aan clientzijde
De app berekent beschikbare plekken als capacity - enrollments.length na het ophalen van de inschrijvingen. Er is geen server-side computed field. Dit betekent dat de waarde mogelijk kort verouderd is bij gelijktijdige inschrijvingen, maar voor de schaal van een clubapp is dit acceptabel.
Trainers kunnen aanmaken en bijwerken, niet verwijderen
Een trainer die per ongeluk een sessie verwijdert, zou inschrijvingen verliezen (cascade delete). De eigenaar als enige verwijderautorisatie is een bewuste veiligheidsdrempel. Dit is afgedwongen via PocketBase deleteRule.