Aller au contenu

API — Parties (Games)

Ce document décrit les endpoints de l'API REST pour la gestion des parties de padel (domain Game).

Base URL

Tous les endpoints sont préfixés par /api/v1.


Endpoints publics

GET /games — Lister les parties publiques ouvertes

Retourne la liste paginée des parties publiques (visibility=public) en statut open ou full, programmées dans le futur.

Paramètre Type Description
type string Filtre par type : friendly ou competitive
environment string Filtre : indoor, semi_covered, outdoor
min_level float Filtre : niveau minimum des joueurs
max_level float Filtre : niveau maximum des joueurs
club_id integer Filtre par club
date_from string Date de début (ISO 8601)
date_to string Date de fin (ISO 8601)
search string Recherche textuelle (club, ville, lieu)
page integer Numéro de page (défaut : 1)
per_page integer Éléments par page (défaut : 15)
{
  "data": [
    {
      "id": 1,
      "type": "friendly",
      "visibility": "public",
      "environment": "indoor",
      "scheduled_at": "2026-03-15T14:00:00+00:00",
      "duration_minutes": 90,
      "location_type": "club",
      "club": { "id": 1, "name": "Padel Club Paris", "city": "Paris" },
      "custom_location": null,
      "is_court_booked": false,
      "min_level": 3.0,
      "max_level": 6.0,
      "sets_count": 3,
      "status": "open",
      "remaining_slots": 3,
      "creator": { "id": 1, "first_name": "Jean", "last_name": "Dupont" },
      "players": [...],
      "created_at": "2026-03-08T10:00:00+00:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 15,
    "total": 1
  }
}

GET /games/{id} — Détail d'une partie

Retourne les détails complets d'une partie avec ses relations (créateur, club, joueurs).

{
  "data": {
    "id": 1,
    "type": "friendly",
    "visibility": "public",
    "environment": "indoor",
    "scheduled_at": "2026-03-15T14:00:00+00:00",
    "duration_minutes": 90,
    "location_type": "club",
    "club": { "id": 1, "name": "Padel Club Paris" },
    "is_court_booked": false,
    "min_level": 3.0,
    "max_level": 6.0,
    "sets_count": 3,
    "status": "open",
    "remaining_slots": 3,
    "creator": { "id": 1, "first_name": "Jean", "last_name": "Dupont" },
    "players": [
      {
        "id": 1,
        "first_name": "Jean",
        "last_name": "Dupont",
        "avatar_url": null,
        "level": 5.0,
        "team": null,
        "position": null,
        "status": "confirmed"
      }
    ]
  }
}
{ "message": "Partie non trouvée." }

Endpoints authentifiés

Authentification requise

Tous les endpoints ci-dessous nécessitent un Bearer Token JWT dans le header Authorization.

POST /games — Créer une partie

Crée une nouvelle partie. Le créateur est automatiquement inscrit comme participant.

Champ Type Obligatoire Description
type string ✅ friendly ou competitive
visibility string ✅ public ou private
environment string ✅ indoor, semi_covered ou outdoor
scheduled_at string ✅ Date/heure ISO 8601 (dans le futur)
duration_minutes integer ✅ 60, 90, 120, 150 ou 180
location_type string ✅ club ou custom
club_id integer Conditionnel Requis si location_type=club
custom_location string Conditionnel Requis si location_type=custom
is_court_booked boolean ✅ true ou false
min_level float ✅ Minimum 1.0
max_level float ✅ Maximum 10.0, ≥ min_level
sets_count integer ✅ 1, 2 ou 3
{
  "message": "Partie créée avec succès.",
  "data": { /* GameResource */ }
}
{
  "message": "The given data was invalid.",
  "errors": {
    "scheduled_at": ["La date doit être dans le futur."],
    "max_level": ["Le niveau max doit être supérieur ou égal au niveau min."]
  }
}

GET /games/my — Mes parties

Liste les parties de l'utilisateur connecté (créées ou rejointes), triées par date décroissante.

POST /games/{game}/join — Rejoindre une partie

Inscrit l'utilisateur à une partie. Si son niveau est hors intervalle, le statut sera pending.

Champ Type Description
team string A ou B (facultatif)
position string left ou right (facultatif)
{
  "message": "Vous avez rejoint la partie.",
  "data": { /* GameResource */ }
}
  • Partie annulée
  • Déjà inscrit
  • Partie complète

POST /games/{game}/leave — Quitter une partie

Retire l'utilisateur d'une partie. La partie repasse en open si elle n'est plus complète.

POST /games/{game}/cancel — Annuler une partie

Annule une partie. Réservé au créateur. Impossible si la partie est en cours ou terminée.


Statuts du cycle de vie

stateDiagram-v2
    [*] --> open : Création
    open --> full : 4 joueurs confirmés
    full --> open : Un joueur quitte
    full --> in_progress : Heure du match (auto)
    in_progress --> finished : Fin manuelle ou +3h
    finished --> score_validated : 4 joueurs valident
    open --> cancelled : Annulation créateur
    full --> cancelled : Annulation créateur
Statut Description
open En attente de joueurs (< 4 confirmés)
full 4 joueurs inscrits, en attente du match
in_progress Match en cours
finished Match terminé, en attente de score
score_validated Score validé par les 4 joueurs
cancelled Annulé par le créateur

Architecture backend

app/Domain/Game/
├── DTOs/
│   └── CreateGameDTO.php       # Objet immuable de transfert
├── Repositories/
│   └── GameRepositoryInterface.php
└── Services/
    └── GameService.php         # Logique métier (créer, rejoindre, quitter, annuler)

app/Infrastructure/Repositories/
└── EloquentGameRepository.php  # Implémentation Eloquent

app/Http/Controllers/Api/V1/
└── GameController.php          # 7 actions avec annotations OpenAPI

app/Http/Requests/Game/
├── CreateGameRequest.php       # Validation création
└── JoinGameRequest.php         # Validation inscription

app/Http/Resources/
└── GameResource.php            # Transformation JSON

Schéma de base de données

Table games

Colonne Type Description
id bigint PK Identifiant
type enum friendly, competitive
visibility enum public, private
environment enum indoor, semi_covered, outdoor
scheduled_at timestamp Date/heure du match
duration_minutes integer Durée en minutes
location_type enum club, custom
club_id FK nullable Référence vers clubs
custom_location varchar Adresse libre
is_court_booked boolean Terrain réservé ?
min_level decimal(3,1) Niveau minimum
max_level decimal(3,1) Niveau maximum
sets_count integer Nombre de sets
status enum Statut du cycle de vie
creator_id FK Référence vers users

Table game_players (pivot)

Colonne Type Description
id bigint PK Identifiant
game_id FK Référence vers games
user_id FK Référence vers users
team enum null A, B
position enum null left, right
status enum confirmed, pending
joined_at timestamp Date d'inscription