Aller au contenu

Plans de salle

Permet à l’application mobile d’afficher le plan du lieu avec des marqueurs interactifs (stands, salles, entrées, services, etc.). Deux endpoints — publics (aucune authentification requise) — qui suivent le même schéma que les endpoints agenda et intervenants.

MéthodeCheminAuthUsage
GET/api/v1/events/{slug}/floor-plansNonListe des plans publiés pour l’événement
GET/api/v1/events/{slug}/floor-plans/{id}NonPlan unique avec la liste complète des marqueurs

Les deux retournent 404 pour un événement non publié ou un plan non publié.


GET /api/v1/events/annual-tech-summit-2026/floor-plans

Réponse légère — utile quand le lieu comporte plusieurs plans (rez-de-chaussée

  • étage par exemple) et que vous voulez un écran « Choisir un plan » avant le rendu détaillé. Aucun marqueur dans cette réponse ; utilisez l’endpoint détail pour les récupérer.
{
"success": true,
"message": "Success",
"data": [
{
"id": 1,
"name": "Rez-de-chaussée",
"image_url": "https://odavent.com/storage/4/rez-de-chaussee.svg",
"width": 1000,
"height": 700,
"sort_order": 0,
"coordinate_system": "percent",
"markers_count": 6,
"updated_at": "2026-04-10T18:05:14+00:00"
}
]
}
ChampNotes
image_urlURL absolue vers l’image du plan (PNG, JPG, SVG ou WebP)
width, heightDimensions de référence en pixels — utilisées pour le rendu des marqueurs
sort_orderOrdre d’affichage défini par l’organisateur ; les plus petites valeurs en premier. Utilisé pour le sélecteur « Choisir un plan ».
coordinate_systemToujours "percent" aujourd’hui. Les x/y des marqueurs sont des pourcentages 0–100 des dimensions de l’image. Champ contractuel — à lire plutôt qu’à coder en dur.
markers_countNombre total de marqueurs interactifs attachés
updated_atMis à jour pour les modifications du plan ET des marqueurs (le modèle marqueur touche son parent). Utilisable comme clé d’invalidation de cache unique.

GET /api/v1/events/annual-tech-summit-2026/floor-plans/1

Renvoie le plan ainsi que tous ses marqueurs, triés par sort_order.

{
"success": true,
"message": "Success",
"data": {
"id": 1,
"name": "Rez-de-chaussée",
"image_url": "https://odavent.com/storage/4/rez-de-chaussee.svg",
"width": 1000,
"height": 700,
"sort_order": 0,
"coordinate_system": "percent",
"markers": [
{
"id": 1,
"type": "entrance",
"label": "Entrée principale",
"description": "Hall A — accueil ouvert dès 8h00",
"x": 50.0,
"y": 95.0,
"link_type": null,
"link_id": null,
"link_url": null,
"color": "#22c55e",
"icon": "door",
"sort_order": 1
},
{
"id": 2,
"type": "booth",
"label": "Stand A4 — Acme Inc",
"description": "Solutions d'automatisation industrielle",
"x": 23.5,
"y": 67.2,
"link_type": "partner",
"link_id": 1,
"link_url": null,
"color": "#6366f1",
"icon": "store",
"sort_order": 2
}
],
"updated_at": "2026-04-10T18:05:14+00:00"
}
}

ChampTypeNotes
idintegerStable entre les modifications ; peut être mis en cache localement
typeenumbooth · room · facility · entrance · exit · info (extensible — voir extensibilité du type)
labelstringToujours affiché lorsque le marqueur est mis en avant
descriptionstring | nullOptionnel ; affiché dans un panneau de détail / bottom sheet au tap
x, yfloatPourcentage des dimensions de l’image (0–100). Voir positionnement
link_typeenum | nullbooth · session · partner · url — détermine la navigation au tap
link_idinteger | nullID de la ressource liée (utilisé avec link_type)
link_urlstring | nullURL externe lorsque link_type === 'url'
colorstringCouleur hexadécimale (#rrggbb) — teinte préférée de l’organisateur
iconstringIndication d’icône (pin, store, screen, door, bath, alert, etc.)
sort_orderintegerLes marqueurs arrivent déjà triés ; à réutiliser côté client pour un rendu stable

Les marqueurs sont enregistrés en pourcentage de la largeur et de la hauteur naturelles de l’image, pas en coordonnées en pixels. Cela les maintient corrects quel que soit le zoom/scaling côté client.

Pour convertir le (x, y) d’un marqueur en pixels sur une image rendue :

pixelX = largeurImageRendue * (marker.x / 100)
pixelY = hauteurImageRendue * (marker.y / 100)

L’origine (0,0) est en haut-gauche ; (100,100) en bas-droite.

Lorsqu’un marqueur est tapoté :

link_typeAction
boothAfficher les détails du stand, ou naviguer vers un écran dédié
sessionNaviguer vers la session dans l’agenda via link_id
partnerNaviguer vers la fiche partenaire via link_id (ex : GET /api/v1/events/{slug}/partners)
urlOuvrir link_url dans le navigateur externe
nullAfficher uniquement label + description dans une popin, sans navigation

L’énumération type peut s’enrichir avec le temps (candidats prévus : stage, food, network_zone, info_desk, parking). Les nouveaux types seront ajoutés sans changement de version d’API.

Les clients DOIVENT gérer les types inconnus de façon défensive — afficher un marqueur neutre avec label + description plutôt que de crasher ou d’ignorer le marqueur. Les champs color et icon restent fiables pour tout nouveau type, donc un rendu qui les respecte se dégrade gracieusement.


Les deux endpoints émettent un header HTTP Last-Modified et honorent If-Modified-Since pour les requêtes conditionnelles. Le pattern client recommandé est stale-while-revalidate :

  1. Mettre en cache la réponse sur disque indéfiniment (ou jusqu’à mise à jour de l’app).
  2. À chaque ouverture d’écran, faire la requête avec la valeur Last-Modified mise en cache passée en If-Modified-Since.
  3. Une réponse 304 Not Modified (~150 octets) signifie « cache valide ».
  4. Une réponse 200 OK remplace le cache.

Les ID des marqueurs sont stables lors des modifications côté organisateur (sémantique upsert-par-ID dans le flux de sauvegarde groupée), donc les deep links comme ?marker=42 survivent aux modifications du plan et les animations client-side entre mises à jour sont fiables.

markers_count sert au gating UI (« masquer l’onglet plan quand zéro »), pas à l’invalidation de cache. Utilisez toujours Last-Modified ou updated_at comme clé d’invalidation — le compte reste stable quand un marqueur est déplacé ou renommé.

L’image servie via image_url provient d’un CDN avec un cache HTTP long — laissez le cache de la plateforme s’en occuper.