Les jobs ASSIGNÉS (marqueurs carte, HTML brut) utilisaient markerIcon =
ligatures material génériques (install→construction, monteur→camion
générique), alors que les jobs NON assignés (carrousel, blocs, gouttes)
utilisent skillSym = icônes SVG custom (échelle+outils, camion-nacelle,
casque). Résultat : même compétence, icône différente selon jour passé
(assigné) vs à venir (non assigné). Unifié sur les SVG custom :
- RouteMap : les marqueurs (arrêts assignés ET gouttes non assignées)
rendent l'icône via un VRAI <q-icon> (h+render) → gère les SVG custom
skillSym comme le reste de l'app ; repli material-icons si échec ;
démontage propre dans clearMarkers/clearPins (pas de fuite).
- PlanificationPage : les arrêts (Tournées + revue Suggérer) passent
skillSym(skill) au lieu de markerIcon ; markerIcon retiré (mort).
⚠️ Rendu carte NON vérifiable en préview (jeu dev sans coordonnées → 0
marqueur). Compile OK, carrousel (25 chips) inchangé, 0 nouvelle erreur.
À confirmer à l'œil en prod (jobs géocodés). Reste : unifier la FORME des
puces (chip/pill/carte) selon contexte — passe design dédiée.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sur la carte Tournées, les jobs NON assignés (props.pins) étaient de
simples gouttes oranges sans icône ni gestion du chevauchement, alors que
les arrêts ASSIGNÉS sont des pastilles round-rect (icône compétence + n°)
qui s'éclatent en éventail au survol quand elles se chevauchent
(recluster/fan). Uniformisé :
- renderPins() rend la MÊME pastille .rm-pill (icône de compétence via
pin.icon = skillSym), variante « non assigné » (.rm-pill-un : bordure
pointillée + halo orange), avec hover onEnter/onLeave.
- recluster() opère désormais sur stopMk.concat(pinMk) → arrêts et jobs
non assignés participent au même éclatement au chevauchement.
- routeUnassignedPins fournit `icon` (skillSym du required_skill/service).
⚠️ Visuel (pastille + éventail) NON vérifiable en préview locale : le jeu
de données dev n'a pas de coordonnées sur les jobs → 0 pin rendu. Code =
miroir fidèle du rendu d'arrêt éprouvé ; map s'initialise, 0 nouvelle
erreur console. À vérifier à l'œil en prod (adresses réelles géocodées).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Batch D — regrouper/situer les non-assignés du jour :
- RouteMap : nouvelle prop `pins` (+ renderPins/clearPins/watch, gouttes oranges couleur=priorité, clic → @pin-click) — miroir de `live`, inclus dans le fit bounds
- Planif Tournées : chips SECTEUR (par ville, comptés, triés) qui filtrent SIMULTANÉMENT la liste « à répartir » ET les gouttes sur la carte ; routeUnassignedPins (coords robustes latitude/lat), clic goutte → détail ; « Suggérer » agit sur le secteur si filtré
Vérifié préview : jour 06/07 → 10 secteurs + 21 gouttes ; clic « STE CLOTILDE » → 4 chips + 4 gouttes (« 4 à répartir / 21 »).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Onglet Tournées : marqueurs « live » de chaque tech (appareil Traccar associé),
rafraîchis ~25 s tant que l'onglet est ouvert. Marqueur = pastille ronde à initiales,
couleur = celle de la tournée du tech, halo pulsé si position fraîche (grisé sans halo
si > 10 min). Tooltip : nom · « il y a X min » · vitesse (km/h) ou « arrêté ».
Bouton « GPS live (N) » pour afficher/masquer. Respecte les chips techs masqués.
- hub roster.js : GET /roster/tech-positions → {positions:[{techId,techName,lat,lon,time,speed}]}
(batch getPositions par appareil). Vérifié prod : 14 positions.
- api/roster.js : techPositions().
- RouteMap.vue : prop `live` + marqueurs .rm-live (halo pulsé, staleness), watch dédié.
- PlanificationPage : polling 25 s (démarré sur l'onglet Tournées, arrêté sinon +
onUnmounted), couleur mappée depuis dayRoutes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Route-stop markers changed from a plain number disc to a rounded-
rectangle "pill" carrying BOTH the job-type icon (material-icons) and
the sequence number, in the tech's route color with a white border —
the standard for markers that show two facts (logistics/route tools).
Number stays bold (primary scan key), icon is context.
- markerIcon(skill): map-safe resolver returning ONLY material-icons
ligatures (skillSym's custom SVGs don't render in a plain <span>);
install→construction, repair→build, tv→live_tv, phone→call, etc.
- stops in dayRoutes + suggestRoutes now carry icon; RouteMap renders
<span.material-icons> + number in .rm-pill. Hover fan-out, hover-to-
front, and cluster logic unchanged (operate on the pill element).
Verified: 43 pills render with glyph+number in tech colors; 8-pin
cluster still fans out on hover.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Click a pin → the FULL job-detail dialog (address, description, ticket
thread, team) instead of a mini popup. RouteMap emits 'stop-click'
(stop payload + route id); stops now carry their job identity
(suggestRoutes → entry/name, dayRoutes → job/name). Parent wires
onReviewStopClick (→ openEntryDetail) and onRoutesStopClick (→
openJobDetail). Verified on both maps (#253081 Tournées, #253286
review).
- Routes now RETURN to the starting point: line + OSRM geometry + km/min
close the loop home→stops→home in RouteMap; the review leg list gets a
"🔄 retour 🏢 bureau TARGO : X min" row (fetchTechRoute appends origin;
loadLegTimes captures returnTo). The solver already optimized round
trips; now the displayed distance/time reflect it. Verified: 11 return
legs shown.
- Fix (0,0) coord blowing out map bounds: suggestRoutes now filters
|lat|>0.01 (dayRoutes already did) and RouteMap.boundsOf guards okLL —
review map was zooming to the Gulf of Guinea. Verified: bounds back on
Montérégie.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause of the bleeding numbers: Mapbox renders ALL circles then ALL
number-symbols in separate passes, so a number can never sit at its
disc's z-level — a hidden pin's number floats over a visible neighbor.
Sort keys can't fix cross-layer stacking.
Fix: stops + homes are now HTML mapboxgl.Marker elements — the number
is a text node INSIDE the colored disc (one element, same level →
correct occlusion, no orphan numbers). Routes stay GL line layers.
- Hover a pin → it scales up (.hot) and its whole route comes to front
(GL rm-line-a filter + .route-hot on same-rid markers).
- Overlapping pins EXPLODE on hover: recluster() unions markers within
24px (projected), computes a radial fan offset per member; entering
any cluster member translates all members' discs outward (CSS
transition) so all are readable/clickable; collapses 200ms after
leave; clusters recompute on moveend, collapse on movestart.
Verified: 43 numbered discs + 16 home markers; an 8-pin stack near
Huntingdon fans out on hover into individually readable pins; distinct
golden-angle colors preserved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Overlap fix: stop circles get circle-sort-key (k) and numbers get
symbol-sort-key (-k) with text-allow-overlap:false — the TOP circle and
the DISPLAYED number are now the same feature; the underneath pin's
number is culled instead of bleeding over its neighbor.
Hover-to-front: three "active" layers (line/stops/numbers, thicker line,
all numbers shown) sit above everything, filtered by rid; mousemove on a
route/stop (or hovering a tech chip / legend item) calls setActive(rid)
→ the whole tournée pops to the foreground; cleared 160ms after leave.
Exposed setActive() alongside fitTo/fitAll. Benefits both maps (review +
Tournées) since it's the shared RouteMap.
Verified: Houssam's magenta route renders on top on chip hover; no more
double numbers at overlapping stops.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
P2 — extract RouteMap.vue (reusable route map): colored per-tech routes
(instant straight lines → real OSRM geometry via hub, module-level
cache), numbered stops with popups, home markers, auto-fit, 'metrics'
emit (real km/min for legends), exposed fitTo(id)/fitAll(). The suggest
review map now uses it — deleted initSuggestMap/refreshSuggestMap/
destroySuggestMap/loadRealRoutes (~90 lines) and the TDZ-prone map
watches; the component is fully reactive on suggestRoutes.
P3 — new "Tournées" board view (grid | day | routes toggle, persisted):
the selected day's REAL routes (assigned jobs from occupancy, ordered by
route_order/start), one color per tech, real OSRM traces + km/min in the
legend, click tech = zoom (fitTo), click stop = detail popup. Day chips
over the visible week. Answers "tournée de la journée sélectionnée, par
tech avec chacun une couleur et trajets optimisés dynamiquement".
Verified: Tournées tab (16 routes, real road-following geometry,
metrics 140.4km/148min etc.); dialog map still renders via RouteMap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>