// Entreprise panel v2 — dramatic header, kinetic info cells const { useState, useEffect, useRef } = React; const GEO_CACHE2 = new Map(); let LAST_GEO_REQ2 = 0; async function geocode2(addr) { if (!addr) return null; if (GEO_CACHE2.has(addr)) return GEO_CACHE2.get(addr); const wait = Math.max(0, 1100 - (Date.now() - LAST_GEO_REQ2)); if (wait) await new Promise(r => setTimeout(r, wait)); LAST_GEO_REQ2 = Date.now(); try { const q = encodeURIComponent(addr + ', Québec, Canada'); const r = await fetch(`https://nominatim.openstreetmap.org/search?format=json&limit=1&q=${q}`, { headers: { 'Accept': 'application/json' } }); if (!r.ok) throw new Error('geo fail'); const j = await r.json(); const hit = j[0]; if (!hit) { GEO_CACHE2.set(addr, null); return null; } const point = { lat: parseFloat(hit.lat), lng: parseFloat(hit.lon) }; GEO_CACHE2.set(addr, point); return point; } catch (e) { GEO_CACHE2.set(addr, null); return null; } } function MapView2({ entreprise, onFail }) { const ref = useRef(null); const mapRef = useRef(null); const [state, setState] = useState('loading'); useEffect(() => { let cancelled = false; setState('loading'); if (!entreprise.adresse) { setState('fail'); return; } (async () => { const point = await geocode2(entreprise.adresse); if (cancelled) return; if (!point) { setState('fail'); onFail?.(); return; } if (!ref.current) return; if (mapRef.current) { mapRef.current.remove(); mapRef.current = null; } const map = L.map(ref.current, { zoomControl: true, attributionControl: false, scrollWheelZoom: false }); mapRef.current = map; const regionBounds = L.latLngBounds([45.0, -75.0], [49.0, -68.0]); map.fitBounds(regionBounds, { padding: [10, 10] }); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 16, attribution: '© OpenStreetMap', }).addTo(map); const icon = L.divIcon({ className: '', html: '
', iconSize: [24, 24], iconAnchor: [12, 12], }); L.marker([point.lat, point.lng], { icon }).addTo(map); setTimeout(() => { if (cancelled) return; map.flyTo([point.lat, point.lng], 8, { duration: 1.2 }); }, 350); setState('ready'); })(); return () => { cancelled = true; if (mapRef.current) { mapRef.current.remove(); mapRef.current = null; } }; }, [entreprise.adresse]); return (
{state === 'fail' && (
Localisation indisponible
{entreprise.adresse ? "L'adresse n'a pu être géolocalisée." : "Aucune adresse renseignée."}
)}
); } function EntreprisePanel2({ entreprise, onClose, isTv }) { const [enter, setEnter] = useState(false); const [mapFailed, setMapFailed] = useState(false); useEffect(() => { requestAnimationFrame(() => setEnter(true)); }, []); useEffect(() => { setMapFailed(false); }, [entreprise.adresse]); useEffect(() => { const onKey = (e) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); }, [onClose]); const phone = window.SVAUtils.formatPhone(entreprise.telephone); const ventes = window.SVAUtils.formatMoney(entreprise.ventes); return (
e.stopPropagation()} style={{ transform: enter ? 'translateX(0)' : 'translateX(60px)', opacity: enter ? 1 : 0, transition: 'transform 360ms cubic-bezier(0.22,1,0.36,1), opacity 360ms cubic-bezier(0.22,1,0.36,1)', }} >
Entreprise

{entreprise.nom}

{entreprise.precision && (
{entreprise.precision}
)}
{entreprise.description && (

{entreprise.description}

)}
{entreprise.site_web && (
Site web
{isTv ? entreprise.site_web.replace(/^https?:\/\//, '').replace(/\/$/, '') : {entreprise.site_web.replace(/^https?:\/\//, '').replace(/\/$/, '')} }
)} {phone && (
Téléphone
{isTv ? phone : {phone}}
)} {ventes && (
Ventes
{ventes}
)} {(entreprise.adresse || entreprise.code_postal) && (
Adresse
{entreprise.adresse} {entreprise.code_postal && (<>
{entreprise.code_postal})}
)} {!entreprise.site_web && !phone && !entreprise.adresse && !ventes && (
Info
Coordonnées non renseignées
)}
{entreprise.adresse && !mapFailed && (
Localisation
setMapFailed(true)} />
)}
); } window.EntreprisePanel2 = EntreprisePanel2;