Skip to content

Add Localized Map Card to Device Details Page#3751

Merged
Baalmart merged 10 commits into
airqo-platform:stagingfrom
BwanikaRobert:Localized-map-card
Jul 9, 2026
Merged

Add Localized Map Card to Device Details Page#3751
Baalmart merged 10 commits into
airqo-platform:stagingfrom
BwanikaRobert:Localized-map-card

Conversation

@BwanikaRobert

@BwanikaRobert BwanikaRobert commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes (What does this PR do?)

Adds an embedded map to the Device Location card on the Device Details page.

  • The card now renders a read-only MiniMap at zoom 13 centred on the
    device's stored coordinates
  • Map is lazy-loaded via React.lazy + Suspense to prevent SSR issues
    with Mapbox GL JS; shows an animated skeleton while loading
  • When a device has no coordinates, a graceful empty state is shown
    (dashed border, MapPin icon, and a short message) instead of a blank space
  • Added a readOnly prop to MiniMap — disables pin dragging and
    click-to-move so the view-only context cannot accidentally mutate coordinates

Status of maturity (all need to be checked before merging):

  • I've tested this locally
  • I consider this code done
  • This change ready to hit production in its current state
  • The title of the PR states what changed and the related issues number (used for the release note).
  • I've included issue number in the "Closes [Vertex: Feature] Add Localized Map Card to Device Details Page #3690" part of the "What are the relevant tickets?" section to link the issue.
  • I've updated corresponding documentation for the changes in this PR.
  • I have written unit and/or e2e tests for my change(s).

How should this be manually tested?

  1. Open Device Details for a device with coordinates — confirm the map
    renders at the correct location
  2. Confirm the pin is not draggable and clicking the map does not move it
  3. Open Device Details for a device without coordinates — confirm the
    empty state renders (MapPin icon + "Location data is currently
    unavailable for this device")
  4. Throttle the network in DevTools and reload — confirm the Suspense
    skeleton (pulse animation) shows before the map tiles load
  5. Open an add/edit device flow — confirm the MiniMap there still allows
    pin dragging (the readOnly prop defaults to false)

What are the relevant tickets?

Screenshots (optional)

image

Summary by CodeRabbit

  • New Features
    • Added a localized device map card with an embedded mini-map centered on saved coordinates (zoom 13) when available.
    • When coordinates are missing, the card now shows a dashed empty-state with a map pin icon.
    • The mini-map is loaded lazily with a pulsing skeleton for smoother perceived performance.
  • Bug Fixes
    • Enforced read-only behavior for the mini-map: marker dragging and click-to-move coordinate updates are disabled when read-only is enabled.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: efe6c339-6a8e-4a94-b67c-a8787c76eede

📥 Commits

Reviewing files that changed from the base of the PR and between 7399629 and 5c13494.

📒 Files selected for processing (1)
  • src/vertex/components/features/devices/device-location-map.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/vertex/components/features/devices/device-location-map.tsx

📝 Walkthrough

Walkthrough

Adds a localized device map card that lazily renders a read-only MiniMap when coordinates exist, shows an empty state when they do not, and updates the changelog with the release heading and feature entry.

Changes

Localized Device Map Card

Layer / File(s) Summary
MiniMap readOnly prop and marker interaction gating
src/vertex/components/features/mini-map/mini-map.tsx
Adds optional readOnly prop (default false) to MiniMapProps; when true, marker dragging is disabled and dragend/click handlers are not registered.
Device location map wrapper and empty state
src/vertex/components/features/devices/device-location-map.tsx
Adds a client-side wrapper that shows a dashed unavailable-state placeholder when coordinates are missing, or a Suspense-wrapped lazy MiniMap with a pulsing fallback when coordinates exist.
Device location card map embedding
src/vertex/components/features/devices/device-location-card.tsx
Marks the card as client-side, removes overflow-hidden, and renders DeviceLocationMap with parsed latitude and longitude.
Changelog documentation
src/vertex/app/changelog.md
Adds the Version 2.0.17 heading and documents Version 2.0.16 for the localized map card and the MiniMap readOnly prop.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: Baalmart

Poem

A map card blooms where device coords land,
With lazy-loaded tiles and a steady hand.
If data is missing, a dashed note appears,
If present, a calm pin cuts through the gears.
Read-only now, with motion set free—
A tiny world, centered neatly.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding a localized map card to the Device Details page.
Linked Issues check ✅ Passed The changes add a Device Location card with a centered map, empty state handling, and lazy-loaded mini-map reuse as required.
Out of Scope Changes check ✅ Passed No unrelated code changes are evident; the edits support the localized map card and its changelog entry.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • JIRA integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/vertex/components/features/devices/device-location-card.tsx (1)

71-82: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Falsy-zero bug: latitude/longitude of 0 incorrectly renders "N/A".

lat ? lat.toFixed(6) : "N/A" and the longitude equivalent treat 0 as falsy, even though 0 is a legitimate coordinate (equator/prime meridian). This is inconsistent with the new hasCoordinates check just above (line 27), which correctly uses !== null. Worth aligning while this data path is being touched for the new map feature.

🐛 Proposed fix
             <div className="text-base font-mono">
-              {lat ? lat.toFixed(6) : "N/A"}
+              {lat !== null ? lat.toFixed(6) : "N/A"}
             </div>
...
             <div className="text-base font-mono">
-              {lon ? lon.toFixed(6) : "N/A"}
+              {lon !== null ? lon.toFixed(6) : "N/A"}
             </div>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/vertex/components/features/devices/device-location-card.tsx` around lines
71 - 82, The latitude/longitude rendering in device-location-card.tsx is using
truthy checks, so a valid coordinate of 0 shows as “N/A”. Update the display
logic in the location card to match the existing hasCoordinates/null-check
approach by checking for null/undefined rather than falsiness, and keep the
logic localized around the latitude and longitude fields so 0 renders correctly
while missing values still show “N/A”.
🧹 Nitpick comments (2)
src/vertex/components/features/mini-map/mini-map.tsx (1)

174-191: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Marker gating looks correct. Draggable flag and handler attachment are properly gated by readOnly, matching the stated contract (no drag/click-to-move in read-only mode).

One minor note: readOnly is read inside the map.on('load', ...) closure but isn't part of the effect's dependency array ([mapMode], line 259). If a caller ever toggles readOnly after mount without changing mapMode, the marker's draggable state and handlers would remain stale. This mirrors the existing pattern for other static props (center, zoom, height), so it's likely intentional given MiniMap is only ever mounted with a fixed readOnly value today (e.g., DeviceLocationCard always passes it as true) — flagging for awareness rather than as a regression.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/vertex/components/features/mini-map/mini-map.tsx` around lines 174 - 191,
The `MiniMap` effect in `mini-map.tsx` reads `readOnly` inside the
`map.on('load', ...)` setup, but the effect only depends on `mapMode`, so
toggling `readOnly` later would leave the marker and event handlers stale.
Update the effect dependency list or otherwise re-initialize the map/marker
setup when `readOnly` changes, and make sure the `markerRef.current` draggable
state plus the `dragend` and `click` handlers in the `MiniMap` setup always
reflect the current `readOnly` value.
src/vertex/components/features/devices/device-location-card.tsx (1)

19-27: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider validating geographic bounds, not just finiteness.

PR objectives state the card should fall back to the empty state when coordinates are "unavailable or invalid." toNumberOrNull/hasCoordinates only check Number.isFinite, so a stray value like lat = 999 would still be treated as valid and passed into MiniMap.

♻️ Proposed range check
   const toNumberOrNull = (v: unknown) => {
     if (v === null || v === undefined || v === '') return null;
     const n = Number(String(v));
     return Number.isFinite(n) ? n : null;
   };

   const lat = toNumberOrNull(device.latitude);
   const lon = toNumberOrNull(device.longitude);
-  const hasCoordinates = lat !== null && lon !== null;
+  const hasCoordinates =
+    lat !== null && lon !== null &&
+    Math.abs(lat) <= 90 && Math.abs(lon) <= 180;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/vertex/components/features/devices/device-location-card.tsx` around lines
19 - 27, The coordinate validation in device-location-card.tsx only checks
finiteness, so invalid geographic values can still reach MiniMap; update
toNumberOrNull and the hasCoordinates check to reject out-of-range
latitude/longitude values as well. Use the existing lat/lon handling in
DeviceLocationCard to enforce valid bounds before rendering the map, and fall
back to the empty state whenever either coordinate is missing or outside
accepted geographic limits.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/vertex/components/features/devices/device-location-card.tsx`:
- Around line 71-82: The latitude/longitude rendering in
device-location-card.tsx is using truthy checks, so a valid coordinate of 0
shows as “N/A”. Update the display logic in the location card to match the
existing hasCoordinates/null-check approach by checking for null/undefined
rather than falsiness, and keep the logic localized around the latitude and
longitude fields so 0 renders correctly while missing values still show “N/A”.

---

Nitpick comments:
In `@src/vertex/components/features/devices/device-location-card.tsx`:
- Around line 19-27: The coordinate validation in device-location-card.tsx only
checks finiteness, so invalid geographic values can still reach MiniMap; update
toNumberOrNull and the hasCoordinates check to reject out-of-range
latitude/longitude values as well. Use the existing lat/lon handling in
DeviceLocationCard to enforce valid bounds before rendering the map, and fall
back to the empty state whenever either coordinate is missing or outside
accepted geographic limits.

In `@src/vertex/components/features/mini-map/mini-map.tsx`:
- Around line 174-191: The `MiniMap` effect in `mini-map.tsx` reads `readOnly`
inside the `map.on('load', ...)` setup, but the effect only depends on
`mapMode`, so toggling `readOnly` later would leave the marker and event
handlers stale. Update the effect dependency list or otherwise re-initialize the
map/marker setup when `readOnly` changes, and make sure the `markerRef.current`
draggable state plus the `dragend` and `click` handlers in the `MiniMap` setup
always reflect the current `readOnly` value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9aa4e11b-220a-470d-baf7-f1d4fdd0dc2c

📥 Commits

Reviewing files that changed from the base of the PR and between af0ed86 and dcb5bf1.

📒 Files selected for processing (3)
  • src/vertex/app/changelog.md
  • src/vertex/components/features/devices/device-location-card.tsx
  • src/vertex/components/features/mini-map/mini-map.tsx

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a localized, embedded map view to the Device Details page by reusing the existing MiniMap component in a read-only mode, and documents the change in the Vertex changelog.

Changes:

  • Added a readOnly prop to MiniMap to disable marker dragging and click-to-move interactions.
  • Embedded a lazy-loaded MiniMap (with a loading skeleton) into the Device Location/Site Details card, with an explicit empty state when coordinates are missing.
  • Added a changelog entry describing the new Device Details localized map card and the MiniMap API update.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/vertex/components/features/mini-map/mini-map.tsx Adds readOnly support to prevent coordinate mutation in view-only contexts.
src/vertex/components/features/devices/device-location-card.tsx Renders a lazy-loaded, read-only MiniMap when coordinates exist; otherwise shows an empty state placeholder.
src/vertex/app/changelog.md Documents the new Device Details map card and the MiniMap readOnly prop addition.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,8 +1,12 @@
import { lazy, Suspense } from "react";

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been addressed. @Baalmart

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

Comment on lines +86 to +105
<div className="px-3 pb-3">
{hasCoordinates ? (
<Suspense fallback={<div className="h-48 rounded-md bg-muted animate-pulse" />}>
<MiniMap
latitude={String(lat)}
longitude={String(lon)}
readOnly
scrollZoom={false}
height="h-48"
zoom={13}
/>
</Suspense>
) : (
<div className="h-48 rounded-md border border-dashed flex flex-col items-center justify-center gap-2 text-muted-foreground bg-muted/30">
<MapPin className="h-6 w-6 opacity-40" />
<p className="text-sm text-center px-4">
Location data is currently unavailable for this device
</p>
</div>
)}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Baalmart Writing tests are not part of this PR.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @BwanikaRobert , thanks for the clarification.
We might want to start writing tests in each of our PRs going forward since it is extremely hard to write tests for the entire application in one go

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

@Codebmk Codebmk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Map not appearing. @BwanikaRobert

Image Image

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

</div>
)}
</div>

@Codebmk Codebmk Jul 8, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this new feature as a component under components/features/devices/ @BwanikaRobert

@Codebmk Codebmk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/vertex/components/features/devices/device-location-map.tsx`:
- Around line 27-29: Update the empty-state copy in the device location map
component so it matches the required wording exactly. In the
device-location-map.tsx component, adjust the message rendered by the location
unavailable state to include the full context “for this device,” keeping the
change scoped to the existing empty-state paragraph.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6c258352-5774-4476-8468-b19f582556ca

📥 Commits

Reviewing files that changed from the base of the PR and between dcb5bf1 and c557eeb.

📒 Files selected for processing (3)
  • src/vertex/app/changelog.md
  • src/vertex/components/features/devices/device-location-card.tsx
  • src/vertex/components/features/devices/device-location-map.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/vertex/app/changelog.md

Comment thread src/vertex/components/features/devices/device-location-map.tsx
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

Matches the linked issue's specified copy for the device location map empty state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

New azure vertex changes available for preview here

@Baalmart
Baalmart merged commit 16675d4 into airqo-platform:staging Jul 9, 2026
16 checks passed
@Baalmart Baalmart mentioned this pull request Jul 9, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Vertex: Feature] Add Localized Map Card to Device Details Page

4 participants