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:
@@ -162,8 +162,23 @@ const LynkDispatchPage = () => {
|
||||
const [isDesktop, setIsDesktop] = useState(() => window.innerWidth >= 1280);
|
||||
const aiPanelRef = useRef(null);
|
||||
|
||||
// Responsive map height for non-desktop — explicit px needed so Leaflet
|
||||
// gets a reliable offsetHeight regardless of CollapsePanel's height:auto chain
|
||||
const calcMapHeight = () => {
|
||||
const w = window.innerWidth;
|
||||
if (w >= 1280) return null; // desktop: DispatchMapPanel handles its own height
|
||||
if (w >= 1024) return '520px'; // iPad Pro 11" landscape / large tablet
|
||||
if (w >= 768) return '460px'; // iPad Air / md tablet
|
||||
if (w >= 640) return '380px'; // small tablet / large phone landscape
|
||||
return '300px'; // mobile portrait
|
||||
};
|
||||
const [mapHeight, setMapHeight] = useState(calcMapHeight);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = () => setIsDesktop(window.innerWidth >= 1280);
|
||||
const handler = () => {
|
||||
setIsDesktop(window.innerWidth >= 1280);
|
||||
setMapHeight(calcMapHeight());
|
||||
};
|
||||
window.addEventListener('resize', handler);
|
||||
return () => window.removeEventListener('resize', handler);
|
||||
}, []);
|
||||
@@ -179,6 +194,16 @@ const LynkDispatchPage = () => {
|
||||
const dragLeft = useCallback((delta) => setLeftWidth(w => Math.min(440, Math.max(220, w + delta))), []);
|
||||
const dragRight = useCallback((delta) => setRightWidth(w => Math.min(440, Math.max(260, w - delta))), []);
|
||||
|
||||
// When the map panel expands on mobile/tablet, fire a synthetic resize
|
||||
// after the CollapsePanel animation (220ms) completes so Leaflet
|
||||
// invalidateSize() in MapController gets a correct container height.
|
||||
useEffect(() => {
|
||||
if (!collapsed.map && !isDesktop) {
|
||||
const t = setTimeout(() => window.dispatchEvent(new Event('resize')), 260);
|
||||
return () => clearTimeout(t);
|
||||
}
|
||||
}, [collapsed.map, isDesktop]);
|
||||
|
||||
const handleSelectLead = (lead) => {
|
||||
if (selectedLead?.id === lead.id) return;
|
||||
setSelectedLead(lead);
|
||||
@@ -328,7 +353,7 @@ const LynkDispatchPage = () => {
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
title={`${efficiencyPct}% of dispatches used AI recommendation — ${100 - efficiencyPct}% were manual overrides`}
|
||||
className="flex items-center gap-1 text-[10px] font-black cursor-default"
|
||||
className="flex items-center gap-1 text-[10px] font-black cursor-default whitespace-nowrap"
|
||||
style={{ color: stormMode ? '#F59E0B' : '#10B981' }}
|
||||
>
|
||||
<span className="w-1 h-1 rounded-full" style={{ backgroundColor: stormMode ? '#F59E0B' : '#10B981' }} />
|
||||
@@ -465,6 +490,7 @@ const LynkDispatchPage = () => {
|
||||
selectedLead={selectedLead}
|
||||
onSelectLead={handleSelectLead}
|
||||
onViewDetails={setViewDetailLead}
|
||||
onQuickAssign={handleAssign}
|
||||
stormMode={stormMode}
|
||||
accent={accent}
|
||||
/>
|
||||
@@ -513,15 +539,18 @@ const LynkDispatchPage = () => {
|
||||
stormMode={stormMode}
|
||||
accent={accent}
|
||||
isDesktop={isDesktop}
|
||||
mapHeight={null}
|
||||
/>
|
||||
) : (
|
||||
<CollapsePanel open={!collapsed.map}>
|
||||
<DispatchMapPanel
|
||||
selectedLead={selectedLead}
|
||||
dispatchLeads={dispatchLeads}
|
||||
reps={effectiveReps}
|
||||
stormMode={stormMode}
|
||||
accent={accent}
|
||||
isDesktop={isDesktop}
|
||||
mapHeight={mapHeight}
|
||||
/>
|
||||
</CollapsePanel>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user