> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/japsinghx/breeze-ios/llms.txt
> Use this file to discover all available pages before exploring further.

# Pollutant Monitoring

> Detailed tracking of six major air pollutants with health impact information

## Overview

The Pollutants Grid provides detailed monitoring of six major air pollutants, each with its own card showing current levels, status, and health information. Users can tap any pollutant to view comprehensive details in a modal sheet.

## Tracked Pollutants

Breeze monitors six key air pollutants:

1. **PM2.5** - Fine Particulate Matter
2. **PM10** - Coarse Particulate Matter
3. **NO₂** - Nitrogen Dioxide
4. **SO₂** - Sulfur Dioxide
5. **O₃** - Ground-Level Ozone
6. **CO** - Carbon Monoxide

## Implementation

### PollutantsGrid Component

The pollutants grid is implemented as a list-style layout with tappable rows:

```swift PollutantsGrid.swift theme={null}
struct PollutantsGrid: View {
    let pollutants: [PollutantReading]
    @State private var selectedPollutant: PollutantReading?
    @State private var detentSelection: PresentationDetent = .large
    
    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // Section Header
            HStack {
                Text("Air Quality Details")
                    .font(.title3)
                    .fontWeight(.semibold)
                
                Spacer()
            }
            
            // Pollutant Cards - Apple-style list
            VStack(spacing: 1) {
                ForEach(Array(pollutants.enumerated()), id: \.element.id) { index, pollutant in
                    PollutantRow(pollutant: pollutant)
                        .onTapGesture {
                            selectedPollutant = pollutant
                            detentSelection = .large
                        }
                        .background(Color.cardBackground)
                }
            }
            .clipShape(RoundedRectangle(cornerRadius: 12))
        }
        .sheet(item: $selectedPollutant) { pollutant in
            PollutantDetailSheet(pollutant: pollutant)
                .presentationDetents([.large, .medium], selection: $detentSelection)
                .presentationDragIndicator(.visible)
        }
    }
}
```

### Pollutant Row Design

Each pollutant is displayed in a clean, information-dense row:

```swift PollutantsGrid.swift theme={null}
struct PollutantRow: View {
    let pollutant: PollutantReading
    
    var body: some View {
        HStack(spacing: 12) {
            // Icon with colored background
            ZStack {
                RoundedRectangle(cornerRadius: 8)
                    .fill(pollutant.status.color.opacity(0.15))
                    .frame(width: 36, height: 36)
                
                Image(systemName: pollutant.type.icon)
                    .font(.system(size: 16, weight: .medium))
                    .foregroundColor(pollutant.status.color)
            }
            
            // Name and description
            VStack(alignment: .leading, spacing: 2) {
                Text(pollutant.type.rawValue)
                    .font(.body)
                    .fontWeight(.medium)
                
                Text(pollutant.type.fullName)
                    .font(.caption)
                    .foregroundColor(.secondary)
            }
            
            Spacer()
            
            // Value and status
            VStack(alignment: .trailing, spacing: 2) {
                HStack(alignment: .firstTextBaseline, spacing: 2) {
                    Text("\(pollutant.roundedValue)")
                        .font(.body)
                        .fontWeight(.semibold)
                    
                    Text(pollutant.type.unit)
                        .font(.caption2)
                        .foregroundColor(.secondary)
                }
                
                Text(pollutant.status.rawValue)
                    .font(.caption)
                    .fontWeight(.medium)
                    .foregroundColor(pollutant.status.color)
            }
            
            // Chevron
            Image(systemName: "chevron.right")
                .font(.caption)
                .foregroundColor(Color(UIColor.tertiaryLabel))
        }
        .padding(.horizontal, 16)
        .padding(.vertical, 12)
    }
}
```

## Pollutant Type Definitions

Each pollutant is defined with its properties in `Pollutant.swift`:

```swift Pollutant.swift theme={null}
enum PollutantType: String, CaseIterable {
    case pm25 = "PM2.5"
    case pm10 = "PM10"
    case no2 = "NO₂"
    case so2 = "SO₂"
    case o3 = "O₃"
    case co = "CO"
    
    var fullName: String {
        switch self {
        case .pm25: return "Fine Particulate Matter (PM2.5)"
        case .pm10: return "Coarse Particulate Matter (PM10)"
        case .no2: return "Nitrogen Dioxide (NO₂)"
        case .so2: return "Sulfur Dioxide (SO₂)"
        case .o3: return "Ground-Level Ozone (O₃)"
        case .co: return "Carbon Monoxide (CO)"
        }
    }
    
    var description: String {
        switch self {
        case .pm25: return "Tiny particles ≤2.5 micrometers that can penetrate deep into lungs and bloodstream."
        case .pm10: return "Inhalable particles ≤10 micrometers from dust, pollen, and mold. Affects respiratory system."
        case .no2: return "Reddish-brown gas from vehicle emissions and power plants. Irritates airways and reduces immunity."
        case .so2: return "Colorless gas from fossil fuel combustion. Can trigger asthma and respiratory issues."
        case .o3: return "Formed by sunlight reacting with pollutants. Harmful to lungs, especially during outdoor activities."
        case .co: return "Odorless, colorless gas from incomplete combustion. Reduces oxygen delivery to body tissues."
        }
    }
    
    var icon: String {
        switch self {
        case .pm25: return "wind"
        case .pm10: return "cloud"
        case .no2: return "car.fill"
        case .so2: return "building.2.fill"
        case .o3: return "sun.max.fill"
        case .co: return "flame.fill"
        }
    }
}
```

## Health Thresholds

Each pollutant has defined health thresholds for good, moderate, and unhealthy levels:

<Tabs>
  <Tab title="PM2.5">
    * **Good**: 0-12 µg/m³
    * **Moderate**: 12.1-35.4 µg/m³
    * **Unhealthy**: >35.4 µg/m³
    * **Icon**: wind
    * **Description**: Fine particulate matter that penetrates deep into lungs
  </Tab>

  <Tab title="PM10">
    * **Good**: 0-54 µg/m³
    * **Moderate**: 54.1-154 µg/m³
    * **Unhealthy**: >154 µg/m³
    * **Icon**: cloud
    * **Description**: Coarse particles from dust, pollen, and mold
  </Tab>

  <Tab title="NO₂">
    * **Good**: 0-53 µg/m³
    * **Moderate**: 53.1-100 µg/m³
    * **Unhealthy**: >100 µg/m³
    * **Icon**: car.fill
    * **Description**: Gas from vehicle emissions and power plants
  </Tab>

  <Tab title="SO₂">
    * **Good**: 0-35 µg/m³
    * **Moderate**: 35.1-75 µg/m³
    * **Unhealthy**: >75 µg/m³
    * **Icon**: building.2.fill
    * **Description**: Gas from fossil fuel combustion
  </Tab>

  <Tab title="O₃">
    * **Good**: 0-54 µg/m³
    * **Moderate**: 54.1-70 µg/m³
    * **Unhealthy**: >70 µg/m³
    * **Icon**: sun.max.fill
    * **Description**: Ground-level ozone formed by sunlight
  </Tab>

  <Tab title="CO">
    * **Good**: 0-4400 µg/m³
    * **Moderate**: 4400.1-9400 µg/m³
    * **Unhealthy**: >9400 µg/m³
    * **Icon**: flame.fill
    * **Description**: Odorless gas from incomplete combustion
  </Tab>
</Tabs>

## Detail Sheet

Tapping a pollutant opens a comprehensive detail sheet with:

### Hero Section

* Large icon with status color background
* Pollutant name and full chemical name
* Current reading with large, bold numbers
* Status badge (Good, Moderate, Unhealthy)

### Information Sections

1. **About** - Detailed description of the pollutant and its sources
2. **Health Ranges** - Visual representation of threshold levels with color coding

```swift PollutantsGrid.swift theme={null}
struct PollutantDetailSheet: View {
    let pollutant: PollutantReading
    
    var body: some View {
        NavigationStack {
            ScrollView {
                VStack(spacing: 24) {
                    // Hero section with icon and name
                    
                    // Current reading card
                    VStack(spacing: 12) {
                        Text("Current Level")
                            .font(.subheadline)
                            .fontWeight(.medium)
                        
                        HStack(alignment: .firstTextBaseline, spacing: 4) {
                            Text("\(pollutant.roundedValue)")
                                .font(.system(size: 56, weight: .bold, design: .rounded))
                                .foregroundColor(pollutant.status.color)
                            
                            Text(pollutant.type.unit)
                                .font(.title3)
                                .foregroundColor(.secondary)
                        }
                        
                        Text(pollutant.status.rawValue)
                            .font(.subheadline)
                            .fontWeight(.semibold)
                            .foregroundColor(.white)
                            .padding(.horizontal, 16)
                            .padding(.vertical, 8)
                            .background(pollutant.status.color)
                            .clipShape(Capsule())
                    }
                    
                    // Health ranges with color indicators
                    VStack(alignment: .leading, spacing: 12) {
                        Text("Health Ranges")
                            .font(.headline)
                        
                        VStack(spacing: 8) {
                            RangeRow(
                                label: "Good",
                                range: "0–\(Int(pollutant.type.goodLimit)) µg/m³",
                                color: .aqiGood,
                                isActive: pollutant.status == .good
                            )
                            RangeRow(
                                label: "Moderate",
                                range: "\(Int(pollutant.type.goodLimit))–\(Int(pollutant.type.moderateLimit)) µg/m³",
                                color: .aqiModerate,
                                isActive: pollutant.status == .moderate
                            )
                            RangeRow(
                                label: "Unhealthy",
                                range: ">\(Int(pollutant.type.moderateLimit)) µg/m³",
                                color: .aqiUnhealthy,
                                isActive: pollutant.status == .unhealthy
                            )
                        }
                    }
                }
            }
        }
    }
}
```

## Status Calculation

Pollutant status is calculated based on threshold values:

```swift Pollutant.swift theme={null}
struct PollutantReading: Identifiable {
    let type: PollutantType
    let value: Double
    
    var status: PollutantStatus {
        if value <= type.goodLimit {
            return .good
        } else if value <= type.moderateLimit {
            return .moderate
        } else {
            return .unhealthy
        }
    }
}
```

## Data Integration

Pollutant data is derived from the air quality response in `DashboardViewModel.swift:119-126`:

```swift theme={null}
self.pollutants = [
    PollutantReading(type: .pm25, value: aq.pm25),
    PollutantReading(type: .pm10, value: aq.pm10),
    PollutantReading(type: .no2, value: aq.nitrogenDioxide),
    PollutantReading(type: .so2, value: aq.sulphurDioxide),
    PollutantReading(type: .o3, value: aq.ozone),
    PollutantReading(type: .co, value: aq.carbonMonoxide)
]
```

## File Locations

* Component: `BreezeApp/Views/Dashboard/PollutantsGrid.swift`
* Model: `BreezeApp/Models/Pollutant.swift`
* Service: `BreezeApp/Services/AirQualityService.swift`
