Commit ba4f8bc
refactor map page to TSX and split into focused modules (#47)
* refactor map page to TSX and split into focused modules
- Extract map concerns into hooks: useMapListingUrl (URL sync + optimistic
pin selection to fix tap flicker), useListingsInView (debounced,
cancellable, padded viewport fetch that preserves prior pins),
useMapCenter (centralised fly-to rules), useIpInitialLocation, and
useMapDrawerScroll.
- Split MapPageClient into MapPageClient + MapListingDrawer and
MapImmersive into MapImmersive + MapPinLayer; move shared types and
helpers into src/utils/mapUtils.ts.
- Convert MapPageClient, MapImmersive, MapPin, MapSearch, and MapSidebar
(plus their barrels) from JSX to TSX with typed props.
- Strip extraneous console logs and add i18n strings for the return-to-
listing button and the pin-loading chip.
Made-with: Cursor
* refactor
* fix styling
* fix(map): address Copilot PR feedback on map hooks and MapView
- Always render Map so DEFAULT_COORDINATES applies when IP lookup is null
- Accept latitude/longitude 0 in MapTiler geolocation response
- Refetch listing when public/private view changes after auth resolves
- Loosen debounce helper typings (document why any[] is needed)
Co-authored-by: Danny White <dnywh@users.noreply.github.com>
* fix(map): address second-pass PR feedback
- useIpInitialLocation: track setTimeout id and clear it in finally + effect
cleanup so the losing race branch can't fire after the network call wins.
- useMapListingUrl: add a monotonic requestTokenRef; fetchBySlug and
selectListingById ignore stale responses (and close invalidates any
in-flight fetch) so older requests can't overwrite newer selections.
- MapPageClient: handleDrawerOpenChange now accepts the open arg and only
calls closeListing when the drawer is actually closing.
- mapUtils: narrow getListingCoordinates / hasValidCoordinates via an
explicit isListingError check instead of casting through isListing.
Made-with: Cursor
* fix(map): attach desktop drawer scroll listener when ref is already set
Previously, the desktop branch of useMapDrawerState only attached the scroll
listener inside the MutationObserver callback. If drawerContentRef.current
was already populated when the effect ran (common on subsequent listing
changes), no DOM mutation fired, the listener never attached, and the sticky
drawer header stayed hidden. Now we attach immediately when the ref is set
and only fall back to the observer when it isn't.
Made-with: Cursor
* fix(map): keep URL/UI in sync on tap failure; handle antimeridian in padBounds
- selectListingById no longer sets the error sentinel when the fetch fails.
Tap-driven fetches happen before the URL is pushed, so the drawer would
either stay closed (swallowing the error) or desync UI and URL while
pointing at the previous listing. The optimistic pin id is reverted and
`selectedListing` is left untouched, so UI and URL stay consistent.
- padBounds now wraps longitudes into [-180, 180] and splits the envelope
into two when the padded viewport crosses the antimeridian. Callers
iterate all returned boxes.
- useListingsInView fetches all returned boxes in parallel and merges
responses, deduping by id.
Made-with: Cursor
* fix(map): restore optimistic pin to resolved listing on tap failure
When selectListingById's fetch fails while a previously resolved listing is
still visible in the drawer, the pin selection was being cleared to null —
leaving the drawer showing listing A with no pin highlighted. Now we capture
the currently-resolved listing id (via a ref mirroring selectedListing.id)
before the optimistic change, and revert to that id on failure so the pin
and the drawer stay in sync.
Made-with: Cursor
* fix(map): cancel in-flight fetch when URL loses listingSlug; cleanups
- useMapListingUrl: bump requestTokenRef when listingSlug becomes null so a
late fetchBySlug response can't re-select the listing after browser back.
- ListingRead: memoize the Supabase client so the thread-loading effect
doesn't re-run on every render; drop unused mapZoomLevel state + effect
(MapThumbnail already uses initialZoomLevel directly).
- ListingChatDrawer: drop the dead listingDisplayName prop (was renamed to
a discarded local); simplify isNested check to !isNested so an omitted
prop is treated as "not nested".
Made-with: Cursor
* fix: narrow thread effect deps; share ListingType with MapPin
- ListingRead: the thread-loading effect depended on the whole realListing
object, so any parent re-render with a new listing identity (even with
the same id/owner_id) refetched the thread. Depend on the specific
fields the effect reads instead.
- MapPin: drop the duplicated ListingPinType union and key the icon map on
the shared ListingType. Adding a new listing type now surfaces as a
compile error in MapPin, keeping the two from drifting out of sync.
Made-with: Cursor
* fix(map): restore IP-based initial centre; assorted review tweaks
- MapView: restore the hasInitialPosition gate. MapLibre's initialViewState
is consumed once at mount, so mounting before the IP lookup resolves
locks the map to DEFAULT_COORDINATES (Brisbane) even after IP data
arrives. The gate waits for either a selected listing or the IP
fallback to resolve before mounting.
- useIpInitialLocation: on timeout or error, fall back to
DEFAULT_COORDINATES so the gate always eventually lifts (addresses the
earlier concern about the map never rendering on IP failure).
- mapUtils: drop the unused DEFAULT_COORDINATES.zoom; ZOOM_LEVEL_DEFAULT
is already the canonical default zoom.
- useMapListingUrl: memoize the Supabase client so fetchBySlug /
selectListingById don't churn on every render.
- MapPin: tighten isListingPinType with hasOwnProperty.call so inherited
prototype keys like "toString" can't incorrectly narrow to ListingType.
Made-with: Cursor
* fix(map): resolve initialCoordinates even when IP lookup is skipped
Deep links (skip: true) would leave initialCoordinates null forever; combined
with a listing that has no coordinates or resolves to an error sentinel, the
<Map> never mounted. Fall back to DEFAULT_COORDINATES on skip so MapView can
always render.
Made-with: Cursor
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Danny White <dnywh@users.noreply.github.com>1 parent 2411aa1 commit ba4f8bc
32 files changed
Lines changed: 2308 additions & 1562 deletions
File tree
- messages
- src
- app
- (core)/(interact)/(stretched)/map
- components
- ListingChatDrawer
- ListingRead
- MapImmersive
- MapPageClient
- MapPin
- MapSearch
- MapSidebar
- features/map
- components
- hooks
- lib
- types
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| 381 | + | |
| 382 | + | |
381 | 383 | | |
382 | 384 | | |
383 | 385 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| 381 | + | |
| 382 | + | |
381 | 383 | | |
382 | 384 | | |
383 | 385 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
378 | 378 | | |
379 | 379 | | |
380 | 380 | | |
| 381 | + | |
| 382 | + | |
381 | 383 | | |
382 | 384 | | |
383 | 385 | | |
| |||
Lines changed: 20 additions & 11 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
1 | 4 | | |
2 | 5 | | |
3 | 6 | | |
4 | | - | |
5 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
6 | 17 | | |
7 | | - | |
8 | | - | |
| 18 | + | |
9 | 19 | | |
10 | 20 | | |
11 | | - | |
12 | 21 | | |
13 | 22 | | |
14 | 23 | | |
15 | 24 | | |
16 | | - | |
17 | 25 | | |
18 | 26 | | |
19 | 27 | | |
| |||
24 | 32 | | |
25 | 33 | | |
26 | 34 | | |
27 | | - | |
| 35 | + | |
28 | 36 | | |
29 | 37 | | |
30 | 38 | | |
31 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
32 | 42 | | |
33 | 43 | | |
34 | 44 | | |
| |||
42 | 52 | | |
43 | 53 | | |
44 | 54 | | |
45 | | - | |
46 | 55 | | |
47 | 56 | | |
48 | 57 | | |
49 | | - | |
| 58 | + | |
50 | 59 | | |
51 | 60 | | |
52 | 61 | | |
53 | 62 | | |
54 | 63 | | |
55 | 64 | | |
56 | | - | |
| 65 | + | |
57 | 66 | | |
58 | 67 | | |
59 | 68 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
494 | 494 | | |
495 | 495 | | |
496 | 496 | | |
497 | | - | |
498 | 497 | | |
499 | 498 | | |
500 | 499 | | |
| |||
Lines changed: 48 additions & 46 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
| 3 | + | |
2 | 4 | | |
3 | 5 | | |
4 | 6 | | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| 11 | + | |
| 12 | + | |
9 | 13 | | |
10 | 14 | | |
11 | 15 | | |
| |||
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
18 | | - | |
| 22 | + | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
| |||
24 | 28 | | |
25 | 29 | | |
26 | 30 | | |
27 | | - | |
| 31 | + | |
28 | 32 | | |
29 | 33 | | |
30 | 34 | | |
31 | 35 | | |
32 | | - | |
| 36 | + | |
33 | 37 | | |
34 | 38 | | |
35 | 39 | | |
36 | | - | |
37 | | - | |
| 40 | + | |
38 | 41 | | |
39 | 42 | | |
40 | 43 | | |
| |||
43 | 46 | | |
44 | 47 | | |
45 | 48 | | |
46 | | - | |
| 49 | + | |
47 | 50 | | |
48 | 51 | | |
49 | 52 | | |
| |||
52 | 55 | | |
53 | 56 | | |
54 | 57 | | |
55 | | - | |
56 | 58 | | |
57 | 59 | | |
58 | 60 | | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
79 | 68 | | |
80 | 69 | | |
81 | | - | |
82 | | - | |
83 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
84 | 76 | | |
85 | 77 | | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
86 | 89 | | |
87 | 90 | | |
88 | 91 | | |
89 | 92 | | |
90 | 93 | | |
91 | 94 | | |
92 | 95 | | |
93 | | - | |
94 | | - | |
95 | | - | |
| 96 | + | |
96 | 97 | | |
97 | 98 | | |
98 | | - | |
99 | | - | |
100 | | - | |
101 | | - | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
102 | 105 | | |
103 | 106 | | |
104 | 107 | | |
| |||
108 | 111 | | |
109 | 112 | | |
110 | 113 | | |
111 | | - | |
112 | | - | |
| 114 | + | |
| 115 | + | |
113 | 116 | | |
114 | 117 | | |
115 | 118 | | |
116 | 119 | | |
117 | 120 | | |
118 | | - | |
| 121 | + | |
119 | 122 | | |
120 | 123 | | |
121 | 124 | | |
| |||
129 | 132 | | |
130 | 133 | | |
131 | 134 | | |
132 | | - | |
133 | | - | |
| 135 | + | |
| 136 | + | |
134 | 137 | | |
135 | 138 | | |
136 | 139 | | |
| |||
154 | 157 | | |
155 | 158 | | |
156 | 159 | | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
161 | 163 | | |
162 | 164 | | |
163 | 165 | | |
| |||
File renamed without changes.
0 commit comments