Project

General

Profile

Actions

Feature #17

closed
CD

Ajouter une vue carte interactive pour visualiser les offres géolocalisées

Feature #17: Ajouter une vue carte interactive pour visualiser les offres géolocalisées

Added by Client Dashboard about 2 months ago. Updated about 2 months ago.

Status:
Shipped
Priority:
Normal
Assignee:
-
Start date:
06/10/2026
Due date:
% Done:

95%

Estimated time:
spec_ref:

conversation:11

build_status:
build_number:
ci_run_url:
scan_status:
scan_report_url:
deploy_status:
preprod_url:
deployed_at:
branch:
pr_url:
security_key:
severity:
paused:

Description

### Problème
Actuellement, les candidats ne peuvent visualiser les offres que sous forme de liste. Cela ne permet pas d’avoir une **vision géographique** des opportunités, ce qui est particulièrement utile pour identifier les zones avec une forte concentration d’offres (ex : télétravail, villes spécifiques) ou pour évaluer les déplacements possibles.

### Contexte
- L’application dispose déjà des **coordonnées GPS** (latitude/longitude) pour la majorité des offres.
- Les filtres existants (salaire, stack, télétravail, etc.) doivent s’appliquer aussi à la carte pour affiner les résultats.
- Sur mobile, l’espace est limité : la carte doit être prioritaire, avec un accès rapide à la liste via un toggle.
- Sur desktop, une **sidebar compacte** à droite doit afficher les offres visibles sur la carte pour une navigation fluide.

### Comportement proposé
- **Toggle liste/carte** : Bouton en haut de l’écran pour basculer entre la vue liste et la vue carte.
- **Carte interactive** :
- Épingles avec **icônes personnalisées** pour indiquer le salaire (💰), le télétravail (🏠), ou le présentiel (🏢).
- **Regroupement des épingles** : Si plusieurs offres sont proches, afficher une seule épingle avec un nombre (ex : "5"). Un clic dézoome pour séparer les épingles.
- **Info-bulle** : Au survol/clic sur une épingle, afficher un résumé (titre, entreprise, salaire, type de contrat) + bouton "Voir détails".
- **Sidebar (desktop)** : Liste compacte des offres visibles sur la carte, synchronisée avec les filtres. Un clic sur une offre centre la carte sur son épingle.
- **Filtres** : Appliqués en temps réel à la carte (les épingles non filtrées disparaissent). La carte ne zoome pas automatiquement.
- **Offres sans localisation précise** : Placer les offres "Remote Europe" au centre de l’Europe avec une étiquette "Remote". Ignorer les offres sans coordonnées GPS sur la carte.
- **Performance** : Limiter à 200 épingles max affichées simultanément. Afficher un message si trop d’offres correspondent aux filtres.

## Acceptance criteria
- [ ] **Toggle liste/carte** : Bouton fonctionnel sur mobile et desktop pour basculer entre les deux vues.
- [ ] **Carte interactive** :
- [ ] Affichage des épingles avec icônes (💰/🏠/🏢) selon les critères (salaire/télétravail/présentiel).
- [ ] Regroupement des épingles proches (ex : "5 offres à Paris") et dézoom automatique au clic.
- [ ] Info-bulle au survol/clic avec résumé de l’offre + bouton "Voir détails".
- [ ] **Sidebar (desktop)** :
- [ ] Liste compacte des offres visibles sur la carte, synchronisée avec les filtres.
- [ ] Clic sur une offre centre la carte sur son épingle et ouvre l’info-bulle.
- [ ] **Filtres** : Appliqués en temps réel à la carte (les épingles non filtrées disparaissent).
- [ ] **Gestion des offres sans localisation** :
- [ ] Offres "Remote Europe" placées au centre de l’Europe avec étiquette "Remote".
- [ ] Offres sans coordonnées GPS ignorées sur la carte (mais visibles en vue liste).
- [ ] **Performance** : Limite de 200 épingles max affichées. Message d’avertissement si trop d’offres correspondent aux filtres.
- [ ] **Responsive** :
- [ ] Mobile : Carte en plein écran, liste masquée (accessible via toggle).
- [ ] Desktop : Carte à gauche (2/3) + sidebar à droite (1/3).
- [ ] **Tests** : Vérifier le comportement avec des filtres extrêmes (ex : "Remote 100%" ou "Salaire > 100k€").
- [ ] **Documentation** : Mettre à jour le guide utilisateur pour expliquer la nouvelle vue carte et ses fonctionnalités.


Files

RA Updated by Redmine Admin about 2 months ago Actions #1

  • % Done changed from 0 to 90

Implémentation terminée sur la branche `feat/offers-map-view` — PR ouverte vers `dev` : https://github.com/omdev-tech/GetYourJob/pull/211

Livré :
- Toggle Liste/Carte (mobile + desktop, persisté en localStorage)
- Carte Leaflet interactive (react-leaflet 5 + supercluster) : épingles emoji (💰 salaire / 🏠 full remote / 🏢 présentiel), regroupement avec compteur, clic = zoom d'expansion
- Info-bulle par épingle (titre, entreprise, localisation, salaire, contrat) + bouton « Voir détails »
- Sidebar desktop (1/3) synchronisée : clic = centrage carte + ouverture info-bulle
- Filtres et recherche appliqués en temps réel à la carte (même endpoint /api/jobs/enhanced, fetch bulk 200)
- Limite 200 épingles + bannière d'avertissement ; offres sans GPS ignorées avec notice ; offres full remote sans coordonnées placées au centre de l'Europe avec étiquette « Remote »
- Fix CSP : autorisation des tuiles OpenStreetMap dans img-src (bloquées par la politique existante)

Vérifié : 15 tests unitaires verts, tsc propre, build prod OK, smoke test navigateur complet (toggle, tuiles, clusters, popup, sidebar, recherche live, responsive mobile).

RA Updated by Redmine Admin about 2 months ago Actions #2

  • Status changed from Submitted to In development

Statut → **In development** (rétroactif — le développement s'est déroulé aujourd'hui sur `feat/offers-map-view`).

RA Updated by Redmine Admin about 2 months ago Actions #3

  • Status changed from In development to QA

Statut → **QA** (dev terminé, QA locale passée).

- PR ouverte vers `dev` : https://github.com/omdev-tech/GetYourJob/pull/211 (branche `feat/offers-map-view`)
- QA effectuée sur build de production locale : toggle Liste/Carte, tuiles OSM (fix CSP), clusters (17 → expansion au clic), info-bulle avec « Voir détails », sidebar synchronisée (clic = centrage + popup), recherche live (180 → 173 épingles), bannières 200 max + offres sans GPS, responsive mobile.
- Prochaine étape : merge de la PR puis déploiement → passage au statut **Preprod** à ce moment-là.

RA Updated by Redmine Admin about 2 months ago Actions #4

PR #211 mergée dans `dev`. PR de promotion vers `preprod` ouverte : https://github.com/omdev-tech/GetYourJob/pull/213 — en attente CI Jenkins, merge dès vert (déploiement preprod automatique). Statut → Preprod après déploiement.

RA Updated by Redmine Admin about 2 months ago Actions #5

  • Status changed from QA to Preprod
  • % Done changed from 90 to 95

Statut → **Preprod** ✅

- PR preprod mergée : https://github.com/omdev-tech/GetYourJob/pull/213 (head preprod `6bc133f`)
- Build + déploiement Jenkins preprod : SUCCESS (continuous-integration/jenkins/branch)
- https://preprod.getyourjob.pro répond (401 nginx Basic-Auth attendu)

**À valider sur preprod** : toggle Liste/Carte sur la home candidat, épingles emoji (💰/🏠/🏢), clusters + zoom au clic, info-bulle « Voir détails », sidebar desktop synchronisée, filtres appliqués en temps réel, bannière 200 max, carte plein écran sur mobile. Après validation → promotion master (gate admin Jenkins).

RA Updated by Redmine Admin about 2 months ago Actions #6

  • Status changed from Preprod to In development

Refonte visuelle de la carte (v2) suite au retour : la carte « faisait vieux » (tuiles OSM brutes, épingles vertes noyées dans le fond vert).

PR vers `dev` : https://github.com/omdev-tech/GetYourJob/pull/215 (branche `feat/offers-map-v2`).

Livré :
- Moteur **MapLibre GL + react-map-gl** (même stack que SeaWave) en remplacement de Leaflet/supercluster ; fond **CARTO Positron** épuré, clustering natif GPU, épingles cercles colorés + halo (ambre=salaire, violet=remote, vert=présentiel), bulles de cluster avec compteur.
- **Popup pro** menée par un **vrai logo d'entreprise** (atome `CompanyLogo` : Clearbit → favicon Google → monogramme coloré, jamais d'icône cassée) + badge de classification, salaire propre (`43–50k€`), secteur/taille/année de création, chips techno, fraîcheur, liens « Voir l'offre » / « Entreprise ». Logos aussi dans la sidebar.
- **Chargement par viewport** : nouvel endpoint léger `GET /api/offers/map?bbox=` + `findForMap` (règles offre active + filtres + bbox, plafond 1000, offres remote quand dézoomé) ; rechargement au pan/zoom (debounce 350ms) ; bouton **Réinitialiser** (filtres + recherche).

Vérifié : 24 tests unitaires, tsc propre, build prod OK, smoke navigateur (tuiles, clusters, popup logo, rechargement au zoom, reset). Reste : attendre CI, merge dev, puis PR dev→preprod.

RA Updated by Redmine Admin about 2 months ago Actions #7

  • Status changed from In development to Preprod

Statut → **Preprod** ✅ (refonte carte v2 déployée)

- PR dev→preprod mergée : https://github.com/omdev-tech/GetYourJob/pull/217 (head preprod `968389f`). NB : la PR dev→preprod directe (#216) était en conflit car preprod portait encore la carte v1 Leaflet (#213) ; résolue via une branche de merge dédiée (`chore/map-v2-preprod`) — maplibre en place, leaflet retiré, CSP v2, lockfile cohérent.
- Build + déploiement Jenkins preprod : SUCCESS.
- Vérifié sur preprod : `GET /api/offers/map?bbox=…` répond (5468 offres zone Paris, plafonné à la limite, brief entreprise avec type + site pour les logos). `https://preprod.getyourjob.pro` répond (401 nginx Basic-Auth attendu).

**À valider sur preprod** (vue Carte sur la home candidat) :
- fond CARTO épuré, épingles colorées + halo bien visibles (💰 ambre / 🏠 violet / 🏢 vert), clusters avec compteur
- popup « pro » : logo entreprise, badge de classification, salaire `43–50k€`, secteur/taille/année, chips techno, « Voir l'offre » / « Entreprise »
- logos aussi dans la sidebar
- rechargement au pan/zoom (chaque déplacement recharge la zone, plafond 1000) + bouton **Réinitialiser**
- responsive mobile

Après validation → promotion master (gate admin Jenkins).

RA Updated by Redmine Admin about 2 months ago Actions #8

Correctif carte (retour preprod) : la carte rechargeait à CHAQUE déplacement (pan/zoom/inertie/fly-to) → requêtes empilées, surcharge, blocage (« boucle infinie »).

Fix → pattern « rechercher dans cette zone » : chargement auto uniquement au 1er affichage et au changement de filtres/recherche ; tout déplacement de carte affiche un bouton flottant **« Rafraîchir dans cette zone »** ; l'utilisateur recharge la zone visible à la demande (un seul fetch, puis le bouton disparaît). Plus aucun fetch automatique au déplacement → plus de boucle.

PR vers `dev` : https://github.com/omdev-tech/GetYourJob/pull/218. Vérifié (build prod + navigateur) : 0 appel API en idle/pan/zoom ; bouton affiché après déplacement (y compris via le contrôle de zoom) ; clic = exactement 1 fetch puis disparition. Suite : attendre CI, merge dev, PR dev→preprod, merge preprod.

RA Updated by Redmine Admin about 2 months ago Actions #9

  • Status changed from Preprod to Shipped

preprod→master mergé → livré en production. Preprod → Shipped.

Actions

Also available in: PDF Atom