mirror of
https://github.com/fabian19921/AR8.git
synced 2026-07-05 21:48:40 +00:00
No description
- HTML 63.4%
- Java 32.7%
- CSS 3.8%
|
|
||
|---|---|---|
| .mvn/wrapper | ||
| docs | ||
| src | ||
| .gitattributes | ||
| .gitignore | ||
| CLAUDE.md | ||
| Dockerfile | ||
| mvnw | ||
| mvnw.cmd | ||
| pom.xml | ||
| README.md | ||
AR-8 — CrossFit Training App
Een full-stack CrossFit training tracking app voor AR-8. Gebruikers kunnen trainingen bekijken, scores loggen, personal records bijhouden, events aanmelden en hun level opbouwen via een puntensysteem.
Live: https://ar-8.nl
GitHub: https://github.com/fabian19921/AR8 (privé)
Tech Stack
| Laag | Technologie |
|---|---|
| Backend | Spring Boot 4, Java 21 |
| Database | PostgreSQL |
| Frontend | Thymeleaf + plain JavaScript |
| Auth | JWT (JSON Web Tokens) |
| Foto opslag | Cloudinary |
| Hosting | Render.com |
| Package | com.laverman.STM1D |
Lokaal opstarten
Vereisten
- Java 21
- Maven
- PostgreSQL database
Stappen
# 1. Clone de repo
git clone https://github.com/fabian19921/AR8.git
cd AR8
# 2. Maak een lokale PostgreSQL database aan
createdb ar8_db
# 3. Stel omgevingsvariabelen in (zie hieronder)
# 4. Start de app
mvn spring-boot:run
De app draait op http://localhost:8080
Omgevingsvariabelen
Zet deze in application.properties of als environment variables op Render:
# Database
spring.datasource.url=jdbc:postgresql://localhost:5432/ar8_db
spring.datasource.username=jouw_gebruikersnaam
spring.datasource.password=jouw_wachtwoord
# JWT
jwt.secret=jouw_jwt_secret
# Cloudinary
cloudinary.cloud-name=jouw_cloud_name
cloudinary.api-key=jouw_api_key
cloudinary.api-secret=jouw_api_secret
# Email (wachtwoord reset)
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=jouw_email
spring.mail.password=jouw_app_wachtwoord
Database migraties
Alle migraties zijn handmatig uitgevoerd. Bij een nieuwe installatie deze SQL queries draaien:
-- Punten systeem
ALTER TABLE users ADD COLUMN IF NOT EXISTS punten INT DEFAULT 0;
UPDATE users SET punten = 0 WHERE punten IS NULL;
-- Profielfoto
ALTER TABLE users ADD COLUMN IF NOT EXISTS profiel_foto_url VARCHAR(500);
ALTER TABLE users ADD COLUMN IF NOT EXISTS profiel_foto_public_id VARCHAR(255);
-- Groepsfoto bij event registraties
ALTER TABLE event_registraties ADD COLUMN IF NOT EXISTS groeps_foto BOOLEAN DEFAULT FALSE;
ALTER TABLE event_registraties ADD COLUMN IF NOT EXISTS groeps_foto_url VARCHAR(500);
ALTER TABLE event_registraties ADD COLUMN IF NOT EXISTS groeps_foto_public_id VARCHAR(255);
-- Ranking timestamp voor maandelijks leaderboard
ALTER TABLE event_registraties ADD COLUMN IF NOT EXISTS ranking_ingevuld_op TIMESTAMP;
UPDATE event_registraties SET ranking_ingevuld_op = '2026-05-01 00:00:00' WHERE ranking_ingevuld = true;
Functionaliteiten
Gebruikers
- Registreren / inloggen via JWT
- Wachtwoord reset via email
- Profielpagina met foto upload (Cloudinary + Cropper.js)
- Rollen:
USERenADMIN
Trainingen
- Trainingsplan per dag aanmaken (ADMIN)
- Blokken: warming up, kracht, WOD, oefenblok, accessory
- Score typen:
kg,tijd,rondes,reps,meter,geen - RX / Scaled toggle per blokje
- Vinkje voor blokjes zonder score
- Buddy workout systeem (max 4 personen)
- Personal Records automatisch bijhouden
- Weekbalk met navigatie
Puntensysteem (50 levels)
- +1 punt per ingevuld score blokje of vinkje
- +5 bonus punten als alle blokjes van een dag gedaan zijn (minimaal 3 blokjes)
- +25 punten per event met eindranking ingevuld
- Buddy gebruikers krijgen dezelfde punten als de captain
- 50 levels van Rookie → Always Ready
- Voortgangsbalk op home pagina
- Maandelijks leaderboard (reset elke maand, toont top 5)
Events
- Events aanmaken met foto (ADMIN)
- Registreren als individueel, buddy of team
- Foto upload per deelnemer met Cropper.js
- Eindranking invullen
- Atleten overzichtspagina per event
WOD Timer
- For Time (telt op, optioneel tijdslimiet)
- EMOM (instelbaar rondes + tijdsduur)
- Interval (werk + rusttijd + rondes)
- 10 seconden aftellen bij start
- Geluidsignalen via Web Audio API
- Scherm blijft aan via Wake Lock API
Overig
- Notities per dag
- Contact pagina
- AR-8 Atleet aanmelding + goedkeuring door admin
Mappenstructuur
src/main/
├── java/com/laverman/STM1D/
│ ├── config/ # CloudinaryConfig, SecurityConfig
│ ├── controller/ # REST controllers
│ ├── model/ # JPA entities
│ ├── repository/ # Spring Data repositories
│ └── service/ # Business logic
└── resources/
├── templates/ # Thymeleaf HTML pagina's
│ └── static/ # style.css, images
└── application.properties
Deployment op Render
- Push naar GitHub (
mainbranch) - Render pikt automatisch de nieuwe versie op (auto-deploy aan)
- SQL migraties handmatig uitvoeren via Render PostgreSQL console
- Environment variables staan ingesteld onder Environment in het Render dashboard
Security
- XSS-bescherming in de frontend: alle dynamische waarden (namen, scores, notificaties, event-/qualifier-velden) worden ge-escaped met de gedeelde helper
esc()uitstatic/js/esc.jsvoordat ze viainnerHTMLgerenderd worden. Nieuwe templates dieinnerHTMLmet dynamische data gebruiken moeten/js/esc.jsincluden enesc()toepassen. - Security headers:
SecurityConfigzet een Content-Security-Policy (o.a.connect-src 'self'tegen token-exfiltratie,frame-ancestors 'none'tegen clickjacking). Externe bronnen die zijn toegestaan:cdnjs.cloudflare.com(cropper.js) enres.cloudinary.com(foto's). - Tests hiervoor staan in
src/test/java/com/laverman/STM1D/config/SecurityHeadersTest.java.
Bekende limieten
- Leaderboard berekent punten real-time voor alle gebruikers — bij >100 gebruikers eventueel caching toevoegen
- Geen push notificaties (Garmin API vereist zakelijke goedkeuring)
trainingplan.htmlheeft een bekend responsive probleem op kleine schermen (< 380px)