Extract components
This commit is contained in:
parent
a48eb945e0
commit
fe46cb3379
30 changed files with 4075 additions and 2610 deletions
177
frontend/src/components/map/map-page/MobileMapPage.tsx
Normal file
177
frontend/src/components/map/map-page/MobileMapPage.tsx
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
import { Suspense, type MutableRefObject, type ReactNode } from 'react';
|
||||
|
||||
import type { FeatureFilters, FeatureMeta, POI, PostcodeGeometry, ViewState } from '../../../types';
|
||||
import type { useMapData } from '../../../hooks/useMapData';
|
||||
import type { TravelTimeEntry } from '../../../hooks/useTravelTime';
|
||||
import type { SearchedLocation } from '../LocationSearch';
|
||||
import MobileBottomSheet from '../MobileBottomSheet';
|
||||
import { MapPinIcon } from '../../ui/icons/MapPinIcon';
|
||||
import type { MapFlyTo } from './types';
|
||||
import { MapFallback, PaneFallback } from './Fallbacks';
|
||||
import { LoadingOverlay } from './LoadingOverlay';
|
||||
import { Map, MobileDrawer } from './lazyComponents';
|
||||
|
||||
type MapData = ReturnType<typeof useMapData>;
|
||||
type RightPaneTab = 'properties' | 'area';
|
||||
|
||||
interface MobileMapPageProps {
|
||||
initialLoading: boolean;
|
||||
mapData: MapData;
|
||||
pois: POI[];
|
||||
mapViewFeature: string | null;
|
||||
filterRange: [number, number] | null;
|
||||
viewSource: 'drag' | 'eye' | null;
|
||||
onCancelPin: () => void;
|
||||
features: FeatureMeta[];
|
||||
selectedHexagonId: string | null;
|
||||
hoveredHexagonId: string | null;
|
||||
onHexagonClick: (id: string, isPostcode?: boolean, geometry?: PostcodeGeometry) => void;
|
||||
onHexagonHover: (h3: string | null, x?: number, y?: number) => void;
|
||||
initialViewState: ViewState;
|
||||
flyToRef: MutableRefObject<MapFlyTo | null>;
|
||||
theme: 'light' | 'dark';
|
||||
filters: FeatureFilters;
|
||||
selectedPostcodeGeometry: PostcodeGeometry | null;
|
||||
onLocationSearched: (location: SearchedLocation | null) => void;
|
||||
onCurrentLocationFound: (lat: number, lng: number) => void;
|
||||
currentLocation: { lat: number; lng: number } | null;
|
||||
travelTimeEntries: TravelTimeEntry[];
|
||||
bottomScreenInset: number;
|
||||
onBottomSheetCoveredHeightChange: (height: number) => void;
|
||||
mobileDrawerOpen: boolean;
|
||||
onMobileDrawerClose: () => void;
|
||||
onMobileDrawerPanelRectChange: (rect: DOMRectReadOnly) => void;
|
||||
rightPaneTab: RightPaneTab;
|
||||
onMobileDrawerTabChange: (tab: RightPaneTab) => void;
|
||||
poiPaneOpen: boolean;
|
||||
onTogglePoiPane: () => void;
|
||||
poiButtonLabel: string;
|
||||
poiPane: ReactNode;
|
||||
filtersPane: ReactNode;
|
||||
mobileLegend: ReactNode;
|
||||
renderAreaPane: () => ReactNode;
|
||||
renderPropertiesPane: () => ReactNode;
|
||||
toasts: ReactNode;
|
||||
upgradeModal: ReactNode;
|
||||
}
|
||||
|
||||
export function MobileMapPage({
|
||||
initialLoading,
|
||||
mapData,
|
||||
pois,
|
||||
mapViewFeature,
|
||||
filterRange,
|
||||
viewSource,
|
||||
onCancelPin,
|
||||
features,
|
||||
selectedHexagonId,
|
||||
hoveredHexagonId,
|
||||
onHexagonClick,
|
||||
onHexagonHover,
|
||||
initialViewState,
|
||||
flyToRef,
|
||||
theme,
|
||||
filters,
|
||||
selectedPostcodeGeometry,
|
||||
onLocationSearched,
|
||||
onCurrentLocationFound,
|
||||
currentLocation,
|
||||
travelTimeEntries,
|
||||
bottomScreenInset,
|
||||
onBottomSheetCoveredHeightChange,
|
||||
mobileDrawerOpen,
|
||||
onMobileDrawerClose,
|
||||
onMobileDrawerPanelRectChange,
|
||||
rightPaneTab,
|
||||
onMobileDrawerTabChange,
|
||||
poiPaneOpen,
|
||||
onTogglePoiPane,
|
||||
poiButtonLabel,
|
||||
poiPane,
|
||||
filtersPane,
|
||||
mobileLegend,
|
||||
renderAreaPane,
|
||||
renderPropertiesPane,
|
||||
toasts,
|
||||
upgradeModal,
|
||||
}: MobileMapPageProps) {
|
||||
return (
|
||||
<div className="flex-1 overflow-hidden relative">
|
||||
<LoadingOverlay show={initialLoading} />
|
||||
|
||||
<div className="absolute inset-0">
|
||||
<Suspense fallback={<MapFallback />}>
|
||||
<Map
|
||||
data={mapData.data}
|
||||
postcodeData={mapData.postcodeData}
|
||||
usePostcodeView={mapData.usePostcodeView}
|
||||
pois={pois}
|
||||
onViewChange={mapData.handleViewChange}
|
||||
viewFeature={mapViewFeature}
|
||||
colorRange={mapData.colorRange}
|
||||
filterRange={filterRange}
|
||||
viewSource={viewSource}
|
||||
onCancelPin={onCancelPin}
|
||||
onResetPreviewScale={mapData.handleResetPreviewScale}
|
||||
canResetPreviewScale={mapData.canResetPreviewScale}
|
||||
features={features}
|
||||
selectedHexagonId={selectedHexagonId}
|
||||
hoveredHexagonId={hoveredHexagonId}
|
||||
onHexagonClick={onHexagonClick}
|
||||
onHexagonHover={onHexagonHover}
|
||||
initialViewState={initialViewState}
|
||||
flyToRef={flyToRef}
|
||||
theme={theme}
|
||||
filters={filters}
|
||||
selectedPostcodeGeometry={selectedPostcodeGeometry}
|
||||
onLocationSearched={onLocationSearched}
|
||||
onCurrentLocationFound={onCurrentLocationFound}
|
||||
currentLocation={currentLocation}
|
||||
bounds={mapData.bounds}
|
||||
hideLegend
|
||||
hideLocationSearch={mobileDrawerOpen && !!selectedHexagonId}
|
||||
travelTimeEntries={travelTimeEntries}
|
||||
bottomScreenInset={bottomScreenInset}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={onTogglePoiPane}
|
||||
className={`absolute top-3 right-3 z-20 p-2 rounded-lg shadow-lg bg-white dark:bg-warm-800 ${poiPaneOpen ? 'text-teal-600 dark:text-teal-400' : 'text-warm-500 dark:text-warm-400 hover:text-teal-600 dark:hover:text-teal-400'}`}
|
||||
aria-label={poiButtonLabel}
|
||||
>
|
||||
<MapPinIcon className="w-5 h-5" />
|
||||
</button>
|
||||
|
||||
{poiPaneOpen && (
|
||||
<div className="absolute top-14 right-3 left-3 z-20 flex h-[45dvh] min-h-0 flex-col overflow-hidden rounded-lg border border-warm-200 bg-white shadow-xl dark:border-warm-700 dark:bg-warm-900">
|
||||
{poiPane}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<MobileBottomSheet
|
||||
legend={mobileLegend}
|
||||
onCoveredHeightChange={onBottomSheetCoveredHeightChange}
|
||||
>
|
||||
{filtersPane}
|
||||
</MobileBottomSheet>
|
||||
|
||||
{mobileDrawerOpen && selectedHexagonId && (
|
||||
<Suspense fallback={<PaneFallback />}>
|
||||
<MobileDrawer
|
||||
onClose={onMobileDrawerClose}
|
||||
renderArea={renderAreaPane}
|
||||
renderProperties={renderPropertiesPane}
|
||||
tab={rightPaneTab}
|
||||
onPanelRectChange={onMobileDrawerPanelRectChange}
|
||||
onTabChange={onMobileDrawerTabChange}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
|
||||
{toasts}
|
||||
{upgradeModal}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue