Feat/clean up and map#15
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds a real-time emergency response map feature to the dashboard using Leaflet and integrates WebSocket updates for live ambulance tracking. The implementation includes map data types, API endpoints, custom styling, animated markers, and a responsive dashboard layout with system status indicators.
- Implements interactive emergency map with ambulances, dispatches, and hospitals using Leaflet and React Leaflet
- Adds WebSocket hook for real-time ambulance location updates with automatic reconnection
- Enhances dashboard and active call pages with improved UI/UX including gradient designs and better visual hierarchy
Reviewed Changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/types/map.ts | Defines TypeScript interfaces for map entities (ambulances, dispatches, hospitals) and their statuses |
| src/api/map.ts | Implements API client functions to fetch map data from backend endpoints |
| src/hooks/useMapWebSocket.ts | Creates WebSocket hook for real-time ambulance location updates with reconnection logic |
| src/components/map/emergency-map.tsx | Main map component with animated markers, popups, and legend for emergency tracking |
| src/styles/leaflet-custom.css | Custom CSS styling for Leaflet map markers, popups, and controls |
| src/app/globals.css | Imports Leaflet stylesheets into global styles |
| src/app/(protected)/dashboard/page.tsx | Integrates emergency map into dashboard with dynamic import and system status cards |
| src/app/(protected)/active-call/page.tsx | Enhances AI insights panel with improved visual design and WebSocket status display |
| src/app/(protected)/active-call/tests/page.test.tsx | Updates test expectations for renamed UI text labels |
| package.json | Adds leaflet, react-leaflet, and @types/leaflet dependencies |
| package-lock.json | Updates lock file with new dependencies |
| .gitignore | Adds .idea/ directory to ignored files |
Comments suppressed due to low confidence (1)
src/app/(protected)/active-call/page.tsx:562
- The
aiInsightsarray is being rendered twice (lines 500-502 and 560-562), causing duplicate insight cards to appear. Remove this duplicate rendering.
{aiInsights.map((insight, index) => (
<InsightCard key={index} insight={insight} />
))}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export interface MapDataResponse { | ||
| ambulances: Ambulance[]; | ||
| dispatches: Dispatch[]; | ||
| hospitals: Hospital[]; | ||
| timestamp: string; | ||
| } |
There was a problem hiding this comment.
The MapData and MapDataResponse interfaces are identical. Consider removing one and using a single interface for both purposes to avoid duplication.
| export interface MapDataResponse { | |
| ambulances: Ambulance[]; | |
| dispatches: Dispatch[]; | |
| hospitals: Hospital[]; | |
| timestamp: string; | |
| } |
| {aiInsights.map((insight, index) => ( | ||
| <InsightCard key={index} insight={insight} /> | ||
| ))} |
There was a problem hiding this comment.
Using array index as key in React lists is an anti-pattern when the list can be reordered or filtered. Consider using a unique identifier from the insight object instead (e.g., key={insight.type} or a combination of properties).
| // Domain event from event bus - this is what the backend actually sends! | ||
| console.log("[MapWebSocket] Domain event:", message.eventName); | ||
|
|
||
| if (message.eventName === "AmbulanceLocationUpdatedEvent") { |
There was a problem hiding this comment.
Consider extracting the event name 'AmbulanceLocationUpdatedEvent' as a constant to avoid magic strings and make it easier to maintain if the event name changes.
| {mapData?.dispatches.filter((d) => d.priority === "P2" || d.priority === "P3") | ||
| .length || 0} |
There was a problem hiding this comment.
The filter operation is executed on every render. Consider memoizing the filtered dispatch counts using useMemo to avoid unnecessary recalculations.
No description provided.