feat: remember map view and add community first-run step

This commit is contained in:
SkateSpots 2026-10-28 22:55:27 +07:00
parent 295dac189f
commit eb7ea50702
3 changed files with 38 additions and 4 deletions

View file

@ -87,6 +87,11 @@ export function FirstRunChecklist() {
{t('mapUi.firstRunWallet')}
</Button>
</Link>
<Link to="/community">
<Button size="sm" variant="outline" className="h-8 border-white/20 font-bold">
{t('communityUi.link')}
</Button>
</Link>
</div>
</div>
);

View file

@ -548,7 +548,7 @@ interface SpotMapProps {
onSpotClick?: (spot: SkateSpot) => void;
selectedSpot?: SkateSpot | null;
onMapClick?: (lat: number, lng: number) => void;
onMapMove?: (center: { lat: number; lon: number }) => void;
onMapMove?: (center: { lat: number; lon: number; zoom?: number }) => void;
enableClickToAdd?: boolean;
className?: string;
weatherEnabled?: boolean;
@ -977,7 +977,7 @@ export function SpotMap({
// Add moveend handler for BTC Map updates
map.on('moveend', () => {
const center = map.getCenter();
onMapMoveRef.current?.({ lat: center.lat, lon: center.lng });
onMapMoveRef.current?.({ lat: center.lat, lon: center.lng, zoom: map.getZoom() });
});
mapInstanceRef.current = map;
@ -1029,7 +1029,7 @@ export function SpotMap({
map.whenReady(() => {
// Trigger initial map move event
const center = map.getCenter();
onMapMoveRef.current?.({ lat: center.lat, lon: center.lng });
onMapMoveRef.current?.({ lat: center.lat, lon: center.lng, zoom: map.getZoom() });
});
}, 100);

View file

@ -678,6 +678,27 @@ export default function MapPage() {
// of the default world view. Resolved once at mount — a fresh fix or a manual
// pan supersedes it. Makes the map feel "already yours" the moment it opens.
const [initialView] = useState(() => {
// Restore the last map view first; a brand-new device falls back to the
// cached location, then to the world view.
try {
const raw = localStorage.getItem('skatespots:map-view');
const saved = raw ? JSON.parse(raw) as { lat?: unknown; lon?: unknown; zoom?: unknown } : null;
if (
saved &&
typeof saved.lat === 'number' && Number.isFinite(saved.lat) &&
typeof saved.lon === 'number' && Number.isFinite(saved.lon) &&
typeof saved.zoom === 'number' && Number.isFinite(saved.zoom)
) {
return {
center: [saved.lat, saved.lon] as [number, number],
zoom: Math.min(18, Math.max(1, saved.zoom)),
lat: saved.lat,
lon: saved.lon,
};
}
} catch {
// fall through to the location/world default
}
const cached = getLastLocation();
return cached
? { center: [cached.lat, cached.lng] as [number, number], zoom: 12, lat: cached.lat, lon: cached.lng }
@ -692,6 +713,14 @@ export default function MapPage() {
lat: initialView.lat,
lon: initialView.lon,
});
const handleMapMove = (center: { lat: number; lon: number; zoom?: number }) => {
setMapCenter({ lat: center.lat, lon: center.lon });
try {
localStorage.setItem('skatespots:map-view', JSON.stringify(center));
} catch {
// storage unavailable — map still works
}
};
// Near Me fly-to state
const [flyTo, setFlyTo] = useState<{ lat: number; lng: number; zoom?: number } | null>(null);
@ -1751,7 +1780,7 @@ export default function MapPage() {
selectedSpot={selectedSpot}
onSpotClick={setSelectedSpot}
onMapClick={handleMapClick}
onMapMove={setMapCenter}
onMapMove={handleMapMove}
enableClickToAdd={!!user}
className="h-full ss-map-floating-toolbar"
weatherEnabled={weatherEnabled}