Build the map shell: drawer accordion and route protection #70
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/map-home-page"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements task 88. Home is now the full-bleed map (
[Authorize]-protected, sinceGET /api/placesis caller-scoped) with aPlaceAccordionin the drawer grouping the caller's places by group. Expanding a group filters the map's markers to it; expanding none shows everything. Selecting a place pans/zooms the map and opens a floatingPlaceDetailPanel— a Blazor panel rather than a Leaflet popup (ADR-0062).State is shared between the drawer (sibling of
@Body, per ADR-0059) and the map through a new scopedMapPlacesState, which also owns the ADR-0049 page-to-completion loop.Accessibility: the burger and every accordion header are real
<button>s witharia-expanded. Opening the drawer moves focus into it, closing returns focus to the toggle, Escape closes it — none of this traps Tab inside the drawer, which nothing in the brief asked for.NavMenuis repurposed as the drawer's secondary links ("Your account", "Groups", "Settings") beneath a new graphical divider, since Home/Places are superseded by the brand link and the accordion respectively.Next free ADR number checked against
mainand both sibling worktrees/branches (feat/group-form,feat/blazor-auth-stateet al.) — 0062 is free everywhere.Not verifiable here (no browser, task 156): rendered layout, actual panning/zoom, marker placement, and whether the detail panel visually clears the drawer on a narrow viewport. Marker-click-to-select and a Leaflet-popup alternative are deliberately out of scope — see ADR-0062's alternatives.
Addressed all four findings:
MapPlacesStatenow takesAuthenticationStateProviderand subscribes toAuthenticationStateChangedfor its own lifetime, clearing every field on a caller change (including sign-out → anonymous). Test:AuthenticationStateChanged_ADifferentCallerSignsInAfterSignOut_NeverExposesThePreviousCallersPlaces.inert="@(!IsOpen)"alongside the transform. Tests inDrawerTestsassert the attribute directly.EnsureLoadedAsyncnow freezesTotalCountfrom page one (matching ADR-0049's wording literally) and has aMaxPagesToReadbackstop against a page that never satisfies it. Boundary tests at 50/51/100/101, plus a repeating-page test and a never-satisfied-total test proving termination, inMapPlacesStateTests. Also fixed an adjacent bug the new cap surfaced: a retry after a partial failure was appending onto stale data rather than starting clean.HomeTestsrendersHomedirectly and drivesMapPlacesState.SelectPlace(the same state a click in the accordion mutates), assertingsetViewis called with the place's coordinates,createMapis not called again, andNavigationManager.Uriis unchanged.ADR-0062 updated with the reasoning for each. Full CI sequence (build,
dotnet format --verify-no-changes, tests) clean on the pinned SDK. Pushed as3950da3.Added the missing regression test:
EnsureLoadedAsync_RetriedAfterAPartialFailure_DoesNotDoubleCountThePagesReadBeforeTheFailure(MapPlacesStateTests).Proved it discriminates by removing
_places.Clear(), running the test, and restoring it. Worth noting what actually happened: without the fix the loop doesn't just duplicate a place, it stops one page early — the stale duplicate from the failed attempt satisfies the total-reached check before the retry ever requests the second page, so a real place goes silently missing. Recorded that in ADR-0062, since it's a sharper failure mode than "double-counting" suggests.Full CI sequence clean on the pinned SDK. Pushed as
c8bb65b.