fix(dispatch): fix Leaflet map blank/partial render on mobile and tablet

- DispatchMapPanel: replace h-full/height:100% with explicit inline px height
  on both wrapper div and MapContainer — CollapsePanel uses height:auto which
  makes percentage heights resolve to 0 giving Leaflet a zero-size canvas
- DispatchMapPanel: accept mapHeight prop from parent for responsive sizing
- LynkDispatchPage: compute responsive mapHeight state (300px mobile →
  380px sm → 460px md → 520px lg tablet) updated on window resize; passed
  as prop to DispatchMapPanel on all non-desktop renders
- LynkDispatchPage: add missing reps={effectiveReps} prop on mobile map render
  so live rep status cycling is reflected on all breakpoints
- LynkDispatchPage: add missing onQuickAssign={handleAssign} on desktop lead
  queue render so Quick Assign button works on desktop
- LynkDispatchPage: add whitespace-nowrap to efficiency badge to prevent
  '89% AI-Dispatched' wrapping to two lines in header
- LynkDispatchPage: dispatch synthetic resize event 260ms after map panel
  expands on mobile/tablet so Leaflet invalidateSize fires post-animation
- DispatchMapPanel: add second invalidateSize call at 320ms (belt-and-suspenders
  alongside 50ms) to cover 220ms CollapsePanel animation on slower devices
- DispatchLeadQueue: enrich DROP_POOL leads with phone, email, source
  sub-details and notes so Lead Quick View shows complete data on drop-in leads
This commit is contained in:
Satyam
2026-03-26 14:31:36 +05:30
parent b804f7cff1
commit 9be8ec911f
3 changed files with 60 additions and 16 deletions
+19 -11
View File
@@ -113,13 +113,19 @@ const MapController = ({ selectedLeadId, leadPos, repPos, routePath }) => {
// Invalidate size on mount and on every window resize so Leaflet fills
// the full flex container — prevents the blank tile area on the right.
// On mobile the map panel is inside a CollapsePanel that animates
// height 0→auto over 220ms, so we need to wait past that before calling
// invalidateSize, otherwise Leaflet initialises at near-zero height.
useEffect(() => {
const invalidate = () => map.invalidateSize({ animate: false });
// Defer one frame so the flex layout has fully settled
const t = setTimeout(invalidate, 50);
// 50ms covers desktop (no animation). 320ms covers the 220ms collapse
// animation with margin so tiles fill correctly on mobile/tablet.
const t1 = setTimeout(invalidate, 50);
const t2 = setTimeout(invalidate, 320);
window.addEventListener('resize', invalidate);
return () => {
clearTimeout(t);
clearTimeout(t1);
clearTimeout(t2);
window.removeEventListener('resize', invalidate);
};
}, [map]);
@@ -186,7 +192,7 @@ const MAP_STYLES = `
// ---------------------------------------------------------------------------
// Main Component
// ---------------------------------------------------------------------------
const DispatchMapPanel = ({ selectedLead, dispatchLeads, reps = DISPATCH_REPS, stormMode, accent, isDesktop }) => {
const DispatchMapPanel = ({ selectedLead, dispatchLeads, reps = DISPATCH_REPS, stormMode, accent, isDesktop, mapHeight }) => {
const { theme } = useTheme();
// Top recommendation for the selected lead
@@ -213,13 +219,15 @@ const DispatchMapPanel = ({ selectedLead, dispatchLeads, reps = DISPATCH_REPS, s
const routeColor = stormMode ? '#F59E0B' : accent;
const containerStyle = isDesktop ? { height: 'calc(72rem + 2.375rem)' } : undefined;
const containerClass = !isDesktop
? 'min-h-[280px] sm:min-h-[360px] md:min-h-[420px]'
: '';
// Explicit pixel height on both the wrapper div and MapContainer.
// Do NOT use h-full / height:100% — the CollapsePanel ancestor has
// height:auto so the percentage chain resolves to 0. Inline px values
// bypass the chain entirely and give Leaflet a reliable offsetHeight.
// mapHeight prop is computed responsively in LynkDispatchPage (300520px).
const mapH = isDesktop ? 'calc(72rem + 2.375rem)' : (mapHeight || '300px');
return (
<div className={`relative overflow-hidden ${containerClass}`} style={containerStyle}>
<div className="relative overflow-hidden" style={{ height: mapH }}>
{/* Inject map animations */}
<style>{MAP_STYLES}</style>
@@ -228,8 +236,8 @@ const DispatchMapPanel = ({ selectedLead, dispatchLeads, reps = DISPATCH_REPS, s
zoom={DEFAULT_ZOOM}
scrollWheelZoom={true}
zoomControl={false}
className="w-full h-full"
style={{ height: '100%', width: '100%' }}
className="w-full"
style={{ height: mapH, width: '100%' }}
>
{/* Tile layer — dark/light aware */}
<TileLayer