Build & Deploy / build (push) Successful in 18s
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
4.1 KiB
Markdown
59 lines
4.1 KiB
Markdown
# StreakFit — Contrat d'API (v1)
|
|
|
|
Base API : `https://api.streakfit.nfteam.ovh`. Front : `https://streakfit.nfteam.ovh`.
|
|
**Auth = Sanctum SPA par COOKIE de session** (pas de token exposé au front). Cookie de session sur `.streakfit.nfteam.ovh`.
|
|
`SANCTUM_STATEFUL_DOMAINS=streakfit.nfteam.ovh`, `SESSION_DOMAIN=.streakfit.nfteam.ovh`, CORS `supports_credentials=true`, origine autorisée = le front.
|
|
**Toute la logique est back.** Le front ne fait que : GET `/sanctum/csrf-cookie`, envoyer le cookie XSRF, afficher.
|
|
|
|
## Auth (couche functional/users)
|
|
- `GET /sanctum/csrf-cookie` — pose le cookie XSRF (Sanctum).
|
|
- `POST /register` `{name,email,password}` → 201, ouvre la session. Crée User (locale/units par défaut) + Streak vide.
|
|
- `POST /login` `{email,password}` → 200 `{user}`, ouvre la session.
|
|
- `POST /logout` → 204.
|
|
- `GET /auth/oidc/redirect` → 302 vers pocket-id (authorization code + PKCE). État en session.
|
|
- `GET /auth/oidc/callback?code&state` → échange le code (OIDC_ISSUER=https://pocket.nfteam.ovh, client via env OIDC_CLIENT_ID/SECRET,
|
|
redirect OIDC_REDIRECT_URI), lie/crée le user par `oidc_sub` puis `email`, ouvre la session, **302 vers APP_FRONT_URL**.
|
|
- `GET /api/me` (auth) → `{ user:{id,name,email,locale,units,timezone,avatar_url}, streak:{current,longest,freezes} }`.
|
|
|
|
## Exercices (public, lecture seule — couche exercises)
|
|
- `GET /api/exercises?search=&body_part=&equipment=&target=&category=&per_page=` → pagination
|
|
`{ data:[{id,name,slug,body_part,equipment,target,image_url,gif_url}], meta:{current_page,last_page,total} }`.
|
|
- `GET /api/exercises/{id}?locale=fr|pt-BR|en` → `{id,name,slug,body_part,category,equipment,target,muscle_group,
|
|
secondary_muscles[], instructions:[...étapes dans la locale (pt-BR→fallback en/fr)], image_url, gif_url, attribution}`.
|
|
- `GET /api/exercises/facets` → valeurs distinctes pour filtres `{body_parts[],equipments[],targets[],categories[]}`.
|
|
|
|
## Routines (auth, scopées user — couche routines)
|
|
CRUD REST : `GET/POST /api/routines`, `GET/PUT/DELETE /api/routines/{id}`.
|
|
Routine = `{id,name,description,is_public,estimated_minutes, exercises:[{exercise_id,position,sets,target_reps,rest_seconds,tempo,target_weight,notes, exercise:{id,name,image_url,target}}]}`.
|
|
POST/PUT accepte `exercises[]` (sync du pivot routine_exercises).
|
|
|
|
## Programmes (auth — couche programs)
|
|
CRUD REST : `/api/programs`. Program = `{id,name,description,duration_weeks,days_per_week, slots:[{week,weekday,routine_id,label}]}`.
|
|
|
|
## Séances / tracking (auth — couche tracking)
|
|
- `POST /api/sessions` `{routine_id?,title?}` → démarre une séance (status=active) → `{session}`.
|
|
- `GET /api/sessions/{id}` → séance + setLogs.
|
|
- `POST /api/sessions/{id}/sets` `{exercise_id,set_number,reps?,weight?,rpe?,duration_seconds?,distance_meters?,is_warmup?}` → log un set → `{set_log}`.
|
|
- `POST /api/sessions/{id}/complete` `{ended_at?}` → passe status=completed (déclenche WorkoutCompleted → streak). → `{session, streak, unlocked_achievements[]}`.
|
|
- `GET /api/history?per_page=` → séances completed paginées.
|
|
- `GET /api/metrics` / `POST /api/metrics` `{measured_on,weight?,body_fat?,notes?}` — mensurations.
|
|
|
|
## Dashboard (LE cœur — couche streaks, controller view-model)
|
|
- `GET /api/dashboard` (auth) → objet prêt-à-afficher :
|
|
```
|
|
{
|
|
streak: { current, longest, freezes_available, last_active_date, flame_level (0..5 selon current), active_today (bool) },
|
|
week: { goal_sessions, done_sessions, days:[{date,done,source}] }, // 7 derniers jours
|
|
recent_sessions: [ {id,title,started_at,total_volume,set_count} ],
|
|
achievements: [ {key,earned_at,label} ],
|
|
suggestion: { type:'routine'|'rest', routine_id?, label } // proposition prochaine séance
|
|
}
|
|
```
|
|
- `GET /api/achievements` → liste complète des badges de l'user.
|
|
|
|
## Conventions
|
|
- Tout scopé par `auth()->id()` (access-control lomkit ou policies) sauf exercices (public).
|
|
- Réponses JSON camelCase OU snake_case — rester COHÉRENT (snake_case, comme ci-dessus).
|
|
- Erreurs : 401 non authentifié, 403 non autorisé, 422 validation (format Laravel `{message,errors}`).
|
|
- Pagination Laravel standard (`meta`, `links`).
|