-
Notifications
You must be signed in to change notification settings - Fork 0
feat(map): Add map component with dynamic markers #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Integrate vue-maplibre-gl with new map component - Add map store for managing map points and bounds - Update CENTER_USA constant to LngLatLike array type - Modify dashboard layout to accommodate map component BREAKING CHANGE: The CENTER_USA constant has been changed from {lng: number, lat: number} to an array [lng, lat] of type LngLatLike. Existing code using the object format must be updated to use the array format.
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis update introduces a Pinia map store to manage and synchronize map markers with location data. The map component is refactored to render markers dynamically from the store, and the map view automatically fits all markers. Supporting type definitions and constants are updated, and layout changes provide improved scrolling and sizing for dashboard elements. A new map library dependency is added. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Dashboard
participant LocationsStore
participant MapStore
participant MapComponent
User->>Dashboard: Loads dashboard page
Dashboard->>LocationsStore: Fetch locations
LocationsStore->>MapStore: Update mapPoints with locations
Dashboard->>MapComponent: Mounts map component
MapComponent->>MapStore: Calls mapStore.init()
MapStore->>MapComponent: mapPoints updated (reactive)
MapComponent->>Map: Render markers for each mapPoint
MapStore->>Map: Fit map bounds to all mapPoints
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~18 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes found. Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
components/app/map.client.vue (1)
14-16
: Consider adding error handling for map initialization.While the
mapStore.init()
call is appropriate, consider adding error handling to gracefully handle initialization failures.onMounted(() => { - mapStore.init(); + try { + mapStore.init(); + } catch (error) { + console.error('Failed to initialize map store:', error); + } });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (8)
components/app/map.client.vue
(2 hunks)lib/constant.ts
(1 hunks)lib/types.ts
(1 hunks)package.json
(1 hunks)pages/dashboard.vue
(2 hunks)pages/dashboard/index.vue
(1 hunks)stores/locations.ts
(1 hunks)stores/map.ts
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
stores/locations.ts (3)
stores/sidebar.ts (1)
useSidebarStore
(8-15)stores/map.ts (1)
useMapStore
(3-24)lib/db/schema/location.ts (1)
location
(8-18)
stores/map.ts (1)
lib/types.ts (1)
MapPoint
(14-17)
🔇 Additional comments (15)
package.json (1)
18-18
: No conflicts detected between map librariesThe added
@indoorequal/vue-maplibre-gl@^8.4.1
dependency aligns with and satisfies thenuxt-maplibre
module’s own@indoorequal/vue-maplibre-gl@^8.3.0
requirement. Both packages:
- Support Vue 3 (including Vue 3.5.13)
- Are actively maintained (recent releases 4 days and 4 months ago)
- Carry permissive licenses (MIT and Apache-2.0)
The direct dependency is intentional for dynamic imports in
stores/map.ts
and introduces no redundancy or version conflicts. No further changes are needed.lib/constant.ts (1)
1-3
: All CENTER_USA references updated – no object‐style usage foundI searched across
.js
,.ts
, and.vue
files and confirmed:• No remaining
CENTER_USA.lng
orCENTER_USA.lat
patterns.
• The only import incomponents/app/map.client.vue
uses:center="CENTER_USA"
with the new array format.No further changes are needed.
pages/dashboard.vue (2)
25-25
: Good responsive design improvement.Adding
shrink-0
prevents the sidebar from collapsing unexpectedly in flex layouts, ensuring consistent sidebar width regardless of content changes.
78-82
: Well-structured layout for map integration.The nested container structure with
overflow-auto
andsize-full
properly handles scrolling and sizing. TheAppMap
component withflex-1
will appropriately fill the remaining space, creating a good user experience with the map persistently visible across dashboard routes.pages/dashboard/index.vue (2)
18-18
: Effective layout adaptation for map integration.The change from
flex-wrap
toflex-nowrap
withoverflow-auto
creates a horizontal scrolling layout that works well with the constrained vertical space now that the map component shares the dashboard area.
22-22
: Good use of shrink-0 for consistent card sizing.Adding
shrink-0
prevents location cards from being compressed in the horizontal flex layout, maintaining consistent card dimensions and readability.components/app/map.client.vue (2)
3-5
: Good store integration pattern.The mapStore import and initialization follows proper Pinia patterns for component-store integration.
26-40
: Excellent dynamic marker implementation – coordinate properties verifiedI’ve confirmed that
point.long
andpoint.lat
align with theMapPoint
(viaLatLongItem
) definitions inlib/types.ts
. No further changes are required.lib/types.ts (1)
10-17
: LGTM! Well-structured type definitions for map functionality.The new
LatLongItem
andMapPoint
types are correctly defined and follow TypeScript best practices. The use of intersection type forMapPoint
appropriately combines location coordinates with display metadata.stores/locations.ts (3)
1-1
: LGTM! Proper import of the new map store.The import statement correctly brings in the map store for integration with location data.
8-8
: LGTM! Proper store instantiation.The map store is correctly instantiated alongside the existing sidebar store.
10-26
: Effect replacement confirmedI searched the entire codebase—there are no remaining
watchEffect
calls, andeffect()
is only used in:
- stores/locations.ts (syncs fetched locations to sidebar & map stores)
- stores/map.ts (updates map bounds when
mapPoints
changes)
effect
is auto-imported in your setup and behaves as intended for immediate, synchronous reactivity. No further action is needed.stores/map.ts (3)
1-4
: LGTM! Proper store structure and type safety.The store is correctly structured with proper type imports and reactive
mapPoints
array using theMapPoint
type.
20-24
: LGTM! Appropriate store exports.The store correctly exports both the
init
function andmapPoints
array for external consumption.
5-5
: Verified:mapStore.init()
Is Invoked on Component MountI confirmed that the
init
function is called in the application:
- In components/app/map.client.vue,
mapStore.init()
is invoked inside theonMounted
hook.No further changes required.
async function init() { | ||
const { useMap } = await import("@indoorequal/vue-maplibre-gl"); | ||
const { LngLatBounds } = await import("maplibre-gl"); | ||
|
||
const map = useMap(); | ||
effect(() => { | ||
const firstPoint = mapPoints.value[0]; | ||
if (!firstPoint) | ||
return; | ||
const bounds = mapPoints.value.reduce((bounds, point) => { | ||
return bounds.extend([point.long, point.lat]); | ||
}, new LngLatBounds([firstPoint.long, firstPoint.lat], [firstPoint.long, firstPoint.lat])); | ||
map.map?.fitBounds(bounds, { padding: 60 }); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for dynamic imports and map operations.
The async init
function correctly uses dynamic imports for code splitting and implements bounds fitting logic. However, consider adding error handling for potential failures.
async function init() {
+ try {
const { useMap } = await import("@indoorequal/vue-maplibre-gl");
const { LngLatBounds } = await import("maplibre-gl");
const map = useMap();
effect(() => {
const firstPoint = mapPoints.value[0];
if (!firstPoint)
return;
const bounds = mapPoints.value.reduce((bounds, point) => {
return bounds.extend([point.long, point.lat]);
}, new LngLatBounds([firstPoint.long, firstPoint.lat], [firstPoint.long, firstPoint.lat]));
- map.map?.fitBounds(bounds, { padding: 60 });
+ try {
+ map.map?.fitBounds(bounds, { padding: 60 });
+ } catch (error) {
+ console.warn('Failed to fit map bounds:', error);
+ }
});
+ } catch (error) {
+ console.error('Failed to initialize map store:', error);
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async function init() { | |
const { useMap } = await import("@indoorequal/vue-maplibre-gl"); | |
const { LngLatBounds } = await import("maplibre-gl"); | |
const map = useMap(); | |
effect(() => { | |
const firstPoint = mapPoints.value[0]; | |
if (!firstPoint) | |
return; | |
const bounds = mapPoints.value.reduce((bounds, point) => { | |
return bounds.extend([point.long, point.lat]); | |
}, new LngLatBounds([firstPoint.long, firstPoint.lat], [firstPoint.long, firstPoint.lat])); | |
map.map?.fitBounds(bounds, { padding: 60 }); | |
}); | |
} | |
async function init() { | |
try { | |
const { useMap } = await import("@indoorequal/vue-maplibre-gl"); | |
const { LngLatBounds } = await import("maplibre-gl"); | |
const map = useMap(); | |
effect(() => { | |
const firstPoint = mapPoints.value[0]; | |
if (!firstPoint) | |
return; | |
const bounds = mapPoints.value.reduce((bounds, point) => { | |
return bounds.extend([point.long, point.lat]); | |
}, new LngLatBounds( | |
[firstPoint.long, firstPoint.lat], | |
[firstPoint.long, firstPoint.lat] | |
)); | |
try { | |
map.map?.fitBounds(bounds, { padding: 60 }); | |
} catch (error) { | |
console.warn('Failed to fit map bounds:', error); | |
} | |
}); | |
} catch (error) { | |
console.error('Failed to initialize map store:', error); | |
} | |
} |
🤖 Prompt for AI Agents
In stores/map.ts around lines 5 to 19, the async init function uses dynamic
imports and map operations without error handling. Wrap the dynamic imports and
map operations in try-catch blocks to catch and handle any errors that may occur
during import or map manipulation. Log or handle errors appropriately to prevent
silent failures and improve robustness.
closes #28
BREAKING CHANGE: The CENTER_USA constant has been changed from {lng: number, lat: number} to an array [lng, lat] of type LngLatLike. Existing code using the object format must be updated to use the array format.
Summary by CodeRabbit
New Features
Improvements
Chores