mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
517 lines
12 KiB
Markdown
517 lines
12 KiB
Markdown
# Map Functionality Critical Analysis & Improvement Recommendations
|
|
|
|
## Executive Summary
|
|
|
|
The map implementation has several **critical bugs**, **performance issues**, and **architectural problems** that need immediate attention. The most severe issue is that **organizations don't have location data** in the backend schema, but the map code attempts to access `org.location.lng/lat`, which will cause runtime errors.
|
|
|
|
---
|
|
|
|
## 🔴 CRITICAL ISSUES
|
|
|
|
### 1. **Missing Location Data (BREAKING BUG)**
|
|
|
|
**Problem:**
|
|
|
|
- Backend `Organization` schema has no `location` or coordinate fields
|
|
- Map code accesses `org.location.lng` and `org.location.lat` (see `useMapInteraction.ts:18`, `AiConnectionLines.tsx:14,19,20`)
|
|
- Locations are stored in `Site` entities, not `Organization` entities
|
|
- `MapMarker` component doesn't receive coordinates prop
|
|
|
|
**Impact:**
|
|
|
|
- Runtime errors when selecting organizations
|
|
- Map markers cannot be positioned
|
|
- Connection lines cannot be drawn
|
|
|
|
**Evidence:**
|
|
|
|
```typescript
|
|
// ❌ BROKEN: Backend schema has no location
|
|
export const backendOrganizationSchema = z.object({
|
|
ID: z.string(),
|
|
Name: z.string(),
|
|
// ... no Latitude/Longitude fields
|
|
});
|
|
|
|
// ❌ BROKEN: Code tries to access non-existent location
|
|
setMapCenter([org.location.lng, org.location.lat]); // useMapInteraction.ts:18
|
|
if (!match.org?.location || !selectedOrg.location) return null; // AiConnectionLines.tsx:14
|
|
```
|
|
|
|
**Fix Required:**
|
|
|
|
1. Fetch Sites for each organization and use Site coordinates
|
|
2. Create a mapping: `Organization ID → Site coordinates`
|
|
3. Update all location access to use Site data
|
|
4. Add fallback handling for organizations without sites
|
|
|
|
---
|
|
|
|
### 2. **MapMarker Missing Coordinates**
|
|
|
|
**Problem:**
|
|
|
|
- `MapMarker` component doesn't use the `Marker` component from `@vnedyalk0v/react19-simple-maps`
|
|
- No `coordinates` prop passed to position markers
|
|
- Markers are rendered as raw SVG `<g>` elements without positioning
|
|
|
|
**Evidence:**
|
|
|
|
```typescript
|
|
// ❌ MapMarker.tsx - no coordinates, no Marker wrapper
|
|
return (
|
|
<g onClick={handleSelect}>
|
|
{/* SVG elements but no positioning */}
|
|
</g>
|
|
);
|
|
```
|
|
|
|
**Fix Required:**
|
|
|
|
```typescript
|
|
// ✅ Should be:
|
|
<Marker coordinates={[org.site.longitude, org.site.latitude]}>
|
|
<MapMarkerContent ... />
|
|
</Marker>
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ PERFORMANCE ISSUES
|
|
|
|
### 3. **No Viewport Culling**
|
|
|
|
**Problem:**
|
|
|
|
- All markers render regardless of viewport bounds
|
|
- With 100+ organizations, this causes significant performance degradation
|
|
- No spatial filtering before rendering
|
|
|
|
**Impact:**
|
|
|
|
- Slow rendering with many organizations
|
|
- Unnecessary DOM/SVG elements
|
|
- High memory usage
|
|
|
|
**Recommendation:**
|
|
|
|
```typescript
|
|
// Implement viewport culling
|
|
const visibleOrgs = useMemo(() => {
|
|
return organizations.filter((org) => {
|
|
const [lng, lat] = [org.site.longitude, org.site.latitude];
|
|
return isInViewport(lng, lat, mapCenter, zoom);
|
|
});
|
|
}, [organizations, mapCenter, zoom]);
|
|
```
|
|
|
|
---
|
|
|
|
### 4. **No Marker Clustering**
|
|
|
|
**Problem:**
|
|
|
|
- Dense marker areas cause visual clutter
|
|
- No clustering algorithm for nearby markers
|
|
- All markers render individually even when overlapping
|
|
|
|
**Recommendation:**
|
|
|
|
- Implement marker clustering (e.g., `supercluster` library)
|
|
- Cluster markers at low zoom levels
|
|
- Show cluster count badges
|
|
- Expand clusters on zoom in
|
|
|
|
---
|
|
|
|
### 5. **Inefficient Sector Lookup**
|
|
|
|
**Problem:**
|
|
|
|
- `SECTORS.find()` called in render loop for every organization
|
|
- O(n\*m) complexity where n=orgs, m=sectors
|
|
- Should be O(1) lookup with Map
|
|
|
|
**Evidence:**
|
|
|
|
```typescript
|
|
// ❌ In render loop - called for every org
|
|
organizations.map((org) => {
|
|
const sector = SECTORS.find((s) => s.nameKey === org.Sector); // O(m) lookup
|
|
// ...
|
|
});
|
|
```
|
|
|
|
**Fix:**
|
|
|
|
```typescript
|
|
// ✅ Pre-compute sector map
|
|
const sectorMap = useMemo(() => {
|
|
return new Map(SECTORS.map((s) => [s.nameKey, s]));
|
|
}, []);
|
|
|
|
// Then O(1) lookup
|
|
const sector = sectorMap.get(org.Sector);
|
|
```
|
|
|
|
---
|
|
|
|
### 6. **No Memoization in InteractiveMap**
|
|
|
|
**Problem:**
|
|
|
|
- `InteractiveMap` component re-renders on every state change
|
|
- No `React.memo` or `useMemo` for expensive operations
|
|
- Marker list recreated on every render
|
|
|
|
**Fix:**
|
|
|
|
```typescript
|
|
const InteractiveMap = React.memo(() => {
|
|
const visibleMarkers = useMemo(() => {
|
|
// Filter and memoize markers
|
|
}, [organizations, mapCenter, zoom, selectedOrg, hoveredOrgId]);
|
|
|
|
// ...
|
|
});
|
|
```
|
|
|
|
---
|
|
|
|
### 7. **Client-Side Filtering of All Data**
|
|
|
|
**Problem:**
|
|
|
|
- All organizations fetched and filtered client-side
|
|
- No backend pagination or spatial filtering
|
|
- Filtering happens on every keystroke (even with debounce)
|
|
|
|
**Recommendation:**
|
|
|
|
- Backend should support:
|
|
- Viewport bounds filtering (`?bounds=minLng,minLat,maxLng,maxLat`)
|
|
- Search with pagination
|
|
- Sector filtering server-side
|
|
|
|
---
|
|
|
|
## 🏗️ ARCHITECTURE ISSUES
|
|
|
|
### 8. **Over-Complex Context Structure**
|
|
|
|
**Problem:**
|
|
|
|
- 5 separate contexts (`MapViewState`, `MapInteractionState`, `MapFilterState`, `MapUIState`, `MapActions`)
|
|
- Context splitting doesn't provide performance benefits (all consumers re-render anyway)
|
|
- Difficult to trace state flow
|
|
|
|
**Recommendation:**
|
|
|
|
- Consolidate to 1-2 contexts
|
|
- Use React Query for server state
|
|
- Keep only UI state in context
|
|
|
|
---
|
|
|
|
### 9. **Missing Spatial Indexing**
|
|
|
|
**Problem:**
|
|
|
|
- No spatial data structure (R-tree, quadtree, etc.)
|
|
- Linear search for nearby organizations
|
|
- No efficient distance calculations
|
|
|
|
**Recommendation:**
|
|
|
|
- Use spatial indexing library (e.g., `rbush`)
|
|
- Pre-index organizations by coordinates
|
|
- Fast nearest-neighbor queries
|
|
|
|
---
|
|
|
|
### 10. **Static Historical Data**
|
|
|
|
**Problem:**
|
|
|
|
- Historical landmarks loaded from static JSON file
|
|
- No backend API for historical data
|
|
- No ability to update without code changes
|
|
|
|
**Recommendation:**
|
|
|
|
- Move to backend API
|
|
- Support dynamic updates
|
|
- Add spatial queries for landmarks
|
|
|
|
---
|
|
|
|
## 🔧 RELIABILITY ISSUES
|
|
|
|
### 11. **No Error Boundaries for Map Rendering**
|
|
|
|
**Problem:**
|
|
|
|
- Map errors can crash entire page
|
|
- No fallback UI for map failures
|
|
- No error recovery
|
|
|
|
**Fix:**
|
|
|
|
```typescript
|
|
<ErrorBoundary fallback={<MapErrorFallback />}>
|
|
<InteractiveMap />
|
|
</ErrorBoundary>
|
|
```
|
|
|
|
---
|
|
|
|
### 12. **No Coordinate Validation**
|
|
|
|
**Problem:**
|
|
|
|
- No validation that coordinates are within valid ranges
|
|
- No handling of missing/invalid coordinates
|
|
- Can cause map projection errors
|
|
|
|
**Fix:**
|
|
|
|
```typescript
|
|
const isValidCoordinate = (lat: number, lng: number) => {
|
|
return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
### 13. **Missing Fallback for Organizations Without Sites**
|
|
|
|
**Problem:**
|
|
|
|
- Organizations may not have associated Sites
|
|
- No handling for missing location data
|
|
- Map will break silently
|
|
|
|
**Fix:**
|
|
|
|
- Filter out organizations without sites
|
|
- Show warning/indicator
|
|
- Provide UI to add site for organization
|
|
|
|
---
|
|
|
|
## ⚡ EFFICIENCY ISSUES
|
|
|
|
### 14. **No Debouncing of Map Movements**
|
|
|
|
**Problem:**
|
|
|
|
- `onMoveEnd` fires on every pan/zoom
|
|
- Can cause excessive state updates
|
|
- No throttling for smooth interactions
|
|
|
|
**Recommendation:**
|
|
|
|
- Debounce `onMoveEnd` (100-200ms)
|
|
- Use `requestAnimationFrame` for smooth updates
|
|
- Batch state updates
|
|
|
|
---
|
|
|
|
### 15. **Inefficient Connection Line Rendering**
|
|
|
|
**Problem:**
|
|
|
|
- All connection lines render even when off-screen
|
|
- No culling for lines outside viewport
|
|
- Lines re-render on every hover state change
|
|
|
|
**Fix:**
|
|
|
|
```typescript
|
|
const visibleLines = useMemo(() => {
|
|
return matches.filter((match) => {
|
|
// Check if line intersects viewport
|
|
return lineIntersectsViewport(match, viewport);
|
|
});
|
|
}, [matches, viewport]);
|
|
```
|
|
|
|
---
|
|
|
|
### 16. **No Lazy Loading**
|
|
|
|
**Problem:**
|
|
|
|
- All organizations loaded upfront
|
|
- No pagination or infinite scroll
|
|
- Large datasets cause initial load delays
|
|
|
|
**Recommendation:**
|
|
|
|
- Implement virtual scrolling for sidebar
|
|
- Lazy load markers as viewport changes
|
|
- Progressive data loading
|
|
|
|
---
|
|
|
|
## 📦 LIBRARY-SPECIFIC ISSUES
|
|
|
|
### 17. **Unused Library Dependency**
|
|
|
|
**Problem:**
|
|
|
|
- `react-zoom-pan-pinch` installed but not used
|
|
- `@vnedyalk0v/react19-simple-maps` has built-in zoom/pan
|
|
- Dead code increases bundle size
|
|
|
|
**Fix:**
|
|
|
|
- Remove unused dependency
|
|
- Clean up package.json
|
|
|
|
---
|
|
|
|
### 18. **Missing Marker Component Usage**
|
|
|
|
**Problem:**
|
|
|
|
- Not using `Marker` component from library
|
|
- Manual SVG positioning instead of library's coordinate system
|
|
- Missing proper projection handling
|
|
|
|
**Fix:**
|
|
|
|
- Use `<Marker coordinates={[lng, lat]}>` wrapper
|
|
- Let library handle coordinate transformation
|
|
|
|
---
|
|
|
|
## 🎯 RECOMMENDED IMPROVEMENTS (Priority Order)
|
|
|
|
### **Phase 1: Critical Fixes (Immediate)**
|
|
|
|
1. ✅ Fix location data access (use Sites instead of Organization.location)
|
|
2. ✅ Add coordinates to MapMarker component
|
|
3. ✅ Add error boundaries
|
|
4. ✅ Add coordinate validation
|
|
|
|
### **Phase 2: Performance (High Priority)**
|
|
|
|
5. ✅ Implement viewport culling
|
|
6. ✅ Add sector lookup Map
|
|
7. ✅ Memoize InteractiveMap and marker lists
|
|
8. ✅ Add marker clustering
|
|
|
|
### **Phase 3: Architecture (Medium Priority)**
|
|
|
|
9. ✅ Consolidate contexts
|
|
10. ✅ Add backend spatial filtering
|
|
11. ✅ Implement spatial indexing
|
|
12. ✅ Move historical data to backend
|
|
|
|
### **Phase 4: Polish (Low Priority)**
|
|
|
|
13. ✅ Debounce map movements
|
|
14. ✅ Optimize connection line rendering
|
|
15. ✅ Add lazy loading
|
|
16. ✅ Remove unused dependencies
|
|
|
|
---
|
|
|
|
## 📊 Performance Metrics to Track
|
|
|
|
1. **Initial Load Time**: Target < 2s
|
|
2. **Time to Interactive**: Target < 3s
|
|
3. **FPS During Pan/Zoom**: Target > 30fps
|
|
4. **Memory Usage**: Monitor for leaks
|
|
5. **Bundle Size**: Track library sizes
|
|
|
|
---
|
|
|
|
## 🔍 Code Quality Issues
|
|
|
|
### Missing Type Safety
|
|
|
|
- `match.org?.location` - location type not defined
|
|
- `geo: any` in MapPicker
|
|
- Missing coordinate types
|
|
|
|
### Inconsistent Patterns
|
|
|
|
- Some components use `React.memo`, others don't
|
|
- Mixed use of `useCallback` vs inline functions
|
|
- Inconsistent error handling
|
|
|
|
### Documentation
|
|
|
|
- Missing JSDoc for complex functions
|
|
- No performance notes
|
|
- No architecture diagrams
|
|
|
|
---
|
|
|
|
## 🚀 Quick Wins
|
|
|
|
1. **Add sector lookup Map** (5 min, high impact)
|
|
2. **Memoize marker list** (10 min, medium impact)
|
|
3. **Add React.memo to InteractiveMap** (2 min, low impact)
|
|
4. **Remove unused dependency** (1 min, low impact)
|
|
5. **Add coordinate validation** (15 min, high reliability)
|
|
|
|
---
|
|
|
|
## 📝 Testing Recommendations
|
|
|
|
1. **Unit Tests:**
|
|
- Viewport culling logic
|
|
- Coordinate validation
|
|
- Sector lookup performance
|
|
|
|
2. **Integration Tests:**
|
|
- Map rendering with 100+ markers
|
|
- Pan/zoom performance
|
|
- Marker selection/hover
|
|
|
|
3. **E2E Tests:**
|
|
- Full map interaction flow
|
|
- Error recovery
|
|
- Performance benchmarks
|
|
|
|
---
|
|
|
|
## 🎓 Best Practices to Adopt
|
|
|
|
1. **Spatial Data Handling:**
|
|
- Always validate coordinates
|
|
- Use spatial indexing for queries
|
|
- Implement viewport culling
|
|
|
|
2. **React Performance:**
|
|
- Memoize expensive computations
|
|
- Use React.memo for pure components
|
|
- Avoid inline object/array creation in render
|
|
|
|
3. **Map Libraries:**
|
|
- Use library components (Marker, etc.)
|
|
- Follow library best practices
|
|
- Monitor library updates
|
|
|
|
4. **State Management:**
|
|
- Keep contexts minimal
|
|
- Use React Query for server state
|
|
- Local state for UI-only concerns
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
The map functionality has **critical bugs** that must be fixed immediately, particularly the location data access issue. Performance optimizations should follow, with viewport culling and clustering providing the biggest impact. The architecture is over-engineered with too many contexts, but this is less urgent than the critical bugs.
|
|
|
|
**Estimated Effort:**
|
|
|
|
- Critical fixes: 4-6 hours
|
|
- Performance improvements: 8-12 hours
|
|
- Architecture refactoring: 6-8 hours
|
|
- Testing & polish: 4-6 hours
|
|
- **Total: 22-32 hours**
|