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