Fix FE
This commit is contained in:
parent
1241132095
commit
54a5c3ca9a
28 changed files with 826 additions and 422 deletions
|
|
@ -26,6 +26,7 @@ import { apiUrl, authHeaders, buildFilterString } from '../../lib/api';
|
|||
import { useFilterCounts } from '../../hooks/useFilterCounts';
|
||||
import { trackEvent } from '../../lib/analytics';
|
||||
import { INITIAL_VIEW_STATE, POSTCODE_ZOOM_THRESHOLD } from '../../lib/consts';
|
||||
import { boundsToCenterZoom } from '../../lib/fit-bounds';
|
||||
import type { OverlayId } from '../../lib/overlays';
|
||||
import { CRIME_TYPE_VALUES } from '../../lib/crime-types';
|
||||
import type { BasemapId } from '../../lib/basemaps';
|
||||
|
|
@ -257,6 +258,14 @@ export default function MapPage({
|
|||
}))
|
||||
);
|
||||
|
||||
// Move the camera to where the matches actually are — flying to the
|
||||
// travel-time anchor often lands on a viewport with zero matches.
|
||||
if (result.matchBounds) {
|
||||
const target = boundsToCenterZoom(result.matchBounds);
|
||||
mapFlyToRef.current?.(target.lat, target.lng, target.zoom, getMobileMapFlyToOptions());
|
||||
return;
|
||||
}
|
||||
|
||||
const firstTravelTime = representable[0]?.tt;
|
||||
if (!firstTravelTime?.slug) return;
|
||||
|
||||
|
|
@ -482,7 +491,15 @@ export default function MapPage({
|
|||
}, []);
|
||||
|
||||
const shareReturnViewRef = useRef(shareCode ? initialViewState : null);
|
||||
// Hide the upgrade modal as soon as the user dismisses it. We can't rely on
|
||||
// the camera fly alone to close it: flying back to the free/shared zone only
|
||||
// clears `licenseRequired` once the resulting refetch returns non-403, and
|
||||
// when the fly target equals the current view (e.g. "back to shared area"
|
||||
// while already at the shared view) `jumpTo` is a no-op, so no refetch fires
|
||||
// and the modal would otherwise stay stuck open.
|
||||
const [upgradeModalDismissed, setUpgradeModalDismissed] = useState(false);
|
||||
const handleZoomToFreeZone = useCallback(() => {
|
||||
setUpgradeModalDismissed(true);
|
||||
const target = shareReturnViewRef.current ?? INITIAL_VIEW_STATE;
|
||||
mapFlyToRef.current?.(target.latitude, target.longitude, target.zoom);
|
||||
}, []);
|
||||
|
|
@ -576,7 +593,6 @@ export default function MapPage({
|
|||
const tutorial = useTutorial(initialLoading, isMobile, deferTutorial || mapData.licenseRequired);
|
||||
const tutorialTheme = useMemo(() => getTutorialStyles(theme), [theme]);
|
||||
const densityLabel = t('mapLegend.historicalMatches');
|
||||
const hasActiveFilters = Object.keys(filters).length > 0 || activeEntries.length > 0;
|
||||
const mobileLegendMeta = useMobileLegendMeta(viewFeature, features);
|
||||
const mapViewFeature = useMapViewFeature(viewFeature);
|
||||
const mobileDensityRange = useMobileDensityRange(mapData);
|
||||
|
|
@ -661,7 +677,13 @@ export default function MapPage({
|
|||
}, [onDashboardReadyChange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (mapData.licenseRequired) trackEvent('Upgrade Modal Shown');
|
||||
if (mapData.licenseRequired) {
|
||||
trackEvent('Upgrade Modal Shown');
|
||||
} else {
|
||||
// Back in a viewable area — re-arm so the modal shows again the next time
|
||||
// the user pans into a gated area.
|
||||
setUpgradeModalDismissed(false);
|
||||
}
|
||||
}, [mapData.licenseRequired]);
|
||||
|
||||
if (screenshotMode) {
|
||||
|
|
@ -856,22 +878,25 @@ export default function MapPage({
|
|||
</div>
|
||||
) : null;
|
||||
|
||||
const upgradeModal = mapData.licenseRequired ? (
|
||||
<Suspense fallback={null}>
|
||||
<UpgradeModal
|
||||
isLoggedIn={!!user}
|
||||
onLoginClick={() =>
|
||||
onCheckoutLoginClick ? onCheckoutLoginClick(checkoutReturnPath) : onLoginClick()
|
||||
}
|
||||
onRegisterClick={() =>
|
||||
onCheckoutRegisterClick ? onCheckoutRegisterClick(checkoutReturnPath) : onRegisterClick()
|
||||
}
|
||||
onStartCheckout={() => license.startCheckout(checkoutReturnPath)}
|
||||
onZoomToFreeZone={handleZoomToFreeZone}
|
||||
isShareReturn={!!shareReturnViewRef.current}
|
||||
/>
|
||||
</Suspense>
|
||||
) : null;
|
||||
const upgradeModal =
|
||||
mapData.licenseRequired && !upgradeModalDismissed ? (
|
||||
<Suspense fallback={null}>
|
||||
<UpgradeModal
|
||||
isLoggedIn={!!user}
|
||||
onLoginClick={() =>
|
||||
onCheckoutLoginClick ? onCheckoutLoginClick(checkoutReturnPath) : onLoginClick()
|
||||
}
|
||||
onRegisterClick={() =>
|
||||
onCheckoutRegisterClick
|
||||
? onCheckoutRegisterClick(checkoutReturnPath)
|
||||
: onRegisterClick()
|
||||
}
|
||||
onStartCheckout={() => license.startCheckout(checkoutReturnPath)}
|
||||
onZoomToFreeZone={handleZoomToFreeZone}
|
||||
isShareReturn={!!shareReturnViewRef.current}
|
||||
/>
|
||||
</Suspense>
|
||||
) : null;
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
|
|
@ -980,7 +1005,7 @@ export default function MapPage({
|
|||
onToggleActualListings={canSeeListings ? handleToggleActualListings : undefined}
|
||||
travelTimeEntries={entries}
|
||||
densityLabel={densityLabel}
|
||||
totalCount={hasActiveFilters ? filterCounts.total : undefined}
|
||||
totalCount={filterCounts.total ?? undefined}
|
||||
poiPaneOpen={poiPaneOpen}
|
||||
onTogglePoiPane={handleTogglePoiPane}
|
||||
poiPane={renderPOIPane()}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue