Skip to content

Latest commit

 

History

History
310 lines (287 loc) · 12.9 KB

MOBILE_ARCHITECTURE.md

File metadata and controls

310 lines (287 loc) · 12.9 KB

Mobile Layout Architecture

Component Hierarchy

page.tsx (Main Component)
├── useIsMobile() hook
│
├── [if mobile]
│   └── MobileLayout
│       ├── Metric Selector Header
│       │   ├── Previous Button (←)
│       │   ├── Current Metric Label
│       │   └── Next Button (→)
│       │
│       └── Cards List (scrollable)
│           ├── Card (Highway 1, County 1)
│           │   ├── Title: Highway + County
│           │   ├── Map Button
│           │   └── MiniSegmentChart (current metric)
│           │
│           ├── Card (Highway 1, County 2)
│           ├── Card (Highway 2, County 1)
│           └── ... (more cards)
│
├── [if charts active]
│   └── ChartsView (full screen overlay)
│       ├── Header
│       │   ├── Back Button
│       │   ├── Title: "PMIS Heat Maps"
│       │   └── Close All Button
│       │
│       ├── Score Gauges (horizontal scroll)
│       │   ├── Gauge 1
│       │   ├── Gauge 2
│       │   └── ...
│       │
│       └── Charts List (vertical scroll)
│           ├── HeatMapModal 1
│           │   ├── Highway Segment Chart
│           │   └── Close Button
│           │
│           ├── HeatMapModal 2
│           └── ...
│
└── MapExplorerModal (when map button clicked)

Data Flow

┌─────────────────────────────────────────────────────────┐
│                       page.tsx                          │
│  ┌────────────────────────────────────────────────┐    │
│  │ 1. Load CSV data (hw_cnty_avg.csv)            │    │
│  │ 2. Process features → processedData[]         │    │
│  │ 3. Load GeoJSON → availableHighways Set       │    │
│  │ 4. Build segment map → segmentDataByHighway   │    │
│  └────────────────────────────────────────────────┘    │
│                          │                              │
│                          ▼                              │
│  ┌────────────────────────────────────────────────┐    │
│  │         TableModalPMIS Component               │    │
│  │  (Processes data and calls callbacks)          │    │
│  │                                                 │    │
│  │  • onDataProcessed(processedData)             │    │
│  │  • onSegmentDataReady(segmentMap)             │    │
│  │  • onAvailableHighwaysReady(highways)         │    │
│  └────────────────────────────────────────────────┘    │
│                          │                              │
│                          ▼                              │
│  ┌────────────────────────────────────────────────┐    │
│  │            Mobile State Updated                │    │
│  │                                                 │    │
│  │  processedData: [{highway, county, scores}]   │    │
│  │  segmentDataByHighwayCounty: Map<key, data>   │    │
│  │  availableHighways: Set<highway>              │    │
│  └────────────────────────────────────────────────┘    │
│                          │                              │
│                          ▼                              │
│  ┌────────────────────────────────────────────────┐    │
│  │  Pass data to MobileLayout as props           │    │
│  └────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

User Interaction Flow

Viewing Metrics

┌─────────────┐
│ User Opens  │
│   Mobile    │
└──────┬──────┘
       │
       ▼
┌─────────────────────┐
│  Card List Shows    │
│  (Default: Cond.)   │
└──────┬──────────────┘
       │
       ├─ Swipe Left ────────┐
       │                      │
       ▼                      ▼
┌──────────────┐      ┌──────────────┐
│ Next Metric  │      │ Prev Metric  │
│ (Distress)   │      │   (Cost)     │
└──────┬───────┘      └──────┬───────┘
       │                      │
       └──────────┬───────────┘
                  │
       ┌──────────┴──────────┐
       │                      │
    Tap Arrow             Tap Arrow
    Buttons              Buttons

Opening Charts

┌──────────────┐
│ User Taps    │
│ Metric Card  │
└──────┬───────┘
       │
       ▼
┌──────────────────────┐
│  handleChartClick()  │
│  • Create chart data │
│  • Add to state      │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│ activeHeatMapData    │
│ length > 0           │
└──────┬───────────────┘
       │
       ▼
┌──────────────────────┐
│  ChartsView Shows    │
│  (Full Screen)       │
└──────┬───────────────┘
       │
       ├─── Back Button ────┐
       │                     │
       ▼                     ▼
┌─────────────┐      ┌──────────────┐
│ Hide Charts │      │ Return to    │
│    View     │      │  Card List   │
└─────────────┘      └──────────────┘

Opening Map

┌──────────────┐
│  User Taps   │
│  Map Button  │
└──────┬───────┘
       │
       ▼
┌───────────────────────┐
│ handleMobileMapClick()│
│ • Get highway         │
│ • Get county          │
│ • Get viewType        │
└──────┬────────────────┘
       │
       ▼
┌───────────────────────┐
│   showMapModal()      │
│ • Set mapModalInfo    │
│ • Set mapModalOpen    │
└──────┬────────────────┘
       │
       ▼
┌───────────────────────┐
│ MapExplorerModal      │
│   (Full Screen)       │
└──────┬────────────────┘
       │
       ▼
┌───────────────────────┐
│  User Closes Modal    │
│  Returns to Cards     │
└───────────────────────┘

Metric Switching Logic

// Current metric index (0-4)
const [currentMetricIndex, setCurrentMetricIndex] = useState(0)

const METRICS = [
  { field: "TX_CONDITION_SCORE", label: "Condition Score" },     // 0
  { field: "TX_DISTRESS_SCORE", label: "Distress Score" },       // 1
  { field: "TX_RIDE_SCORE", label: "Ride Score" },               // 2
  { field: "TX_AADT_CURRENT", label: "AADT" },                   // 3
  { field: "TX_MAINTENANCE_COST_AMT", label: "Maintenance Cost" }// 4
]

// Swipe detection
onTouchStart → Store start X position
onTouchMove  → Store end X position
onTouchEnd   → Calculate distance
  ├─ If distance > 50px left  → Next metric (index + 1) % 5
  └─ If distance > 50px right → Prev metric (index - 1 + 5) % 5

Screen States

State 1: Card List (Default)

┌─────────────────────────┐
│ ← Condition Score    → │  ← Header
│ Swipe to change (1/5)  │
├─────────────────────────┤
│                         │
│  ┌───────────────────┐ │
│  │ IH 35 • Travis    │ │
│  │ [Map Button]      │ │
│  │ ┌───────────────┐ │ │
│  │ │ Chart Preview │ │ │  ← Card 1
│  │ └───────────────┘ │ │
│  └───────────────────┘ │
│                         │
│  ┌───────────────────┐ │
│  │ US 290 • Travis   │ │
│  │ [Map Button]      │ │
│  │ ┌───────────────┐ │ │  ← Card 2
│  │ │ Chart Preview │ │ │
│  │ └───────────────┘ │ │
│  └───────────────────┘ │
│         ...             │
└─────────────────────────┘

State 2: Charts View

┌─────────────────────────┐
│ ← PMIS Heat Maps  [✕]  │  ← Header
├─────────────────────────┤
│ [Gauge1][Gauge2][...]   │  ← Score Gauges
├─────────────────────────┤
│                         │
│ ┌─────────────────────┐ │
│ │ IH 35 • Travis   [✕]│ │
│ │ ┌─────────────────┐ │ │
│ │ │  Highway Chart  │ │ │  ← Chart 1
│ │ │                 │ │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────┘ │
│                         │
│ ┌─────────────────────┐ │
│ │ US 290 • Travis  [✕]│ │
│ │ ┌─────────────────┐ │ │
│ │ │  Highway Chart  │ │ │  ← Chart 2
│ │ │                 │ │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────┘ │
│         ...             │
└─────────────────────────┘

State 3: Map Modal (Overlay)

┌─────────────────────────┐
│ PMIS Explorer - IH 35   │
│                    [✕]  │
├─────────────────────────┤
│                         │
│        [Map View]       │
│                         │
│    Interactive Map      │
│    with Highway         │
│    Highlighted          │
│                         │
│  [Year Selector: 2022]  │
│                         │
└─────────────────────────┘

Responsive Breakpoints

Mobile:      < 768px  → MobileLayout
Tablet:    768-1024px → Desktop Layout (grid)
Desktop:   > 1024px   → Desktop Layout (grid)

Performance Optimizations

  1. React.memo on Card and TableRow components
  2. useMemo for expensive calculations:
    • Processed data
    • Segment data mapping
    • Filtered and sorted data
  3. useCallback for event handlers:
    • Map clicks
    • Chart clicks
    • Remove operations
  4. Lazy loading with dynamic imports:
    • MobileLayout
    • HeatMapModal
    • Score gauges
    • Chart components
  5. Deferred rendering in MiniSegmentChart to prevent blocking