{{ theme.skipToContentLabel || 'Skip to content' }}

Heatmap Value Filter - Design Document

Overview

Add a flexible value filter to the Heatmap feature that allows users to filter PM10 data points by specific numeric conditions.

Requirements

Functional Requirements

  1. Filter Modes: Support 7 filter modes:

    • = (equals) - Filter out points equal to the value
    • (not equals) - Filter out points not equal to the value
    • > (greater than) - Filter out points greater than the value
    • (greater than or equal) - Filter out points greater than or equal to the value
    • < (less than) - Filter out points less than the value
    • (less than or equal) - Filter out points less than or equal to the value
    • Range - Only show points within the specified min/max range
  2. UI Components:

    • Toggle switch to enable/disable the filter
    • Button group for mode selection
    • Input field(s) for value entry (single or dual for range)
    • Real-time validation with error messages
    • Display count of filtered data points
  3. Behavior:

    • Default: disabled
    • Independent from "Hide Zero Values" toggle (both filters stack)
    • Real-time filtering as user types (with validation)

Non-Functional Requirements

  • Consistent UI style with existing controls
  • Performant filtering using useMemo
  • Accessible (proper ARIA attributes)

UI Design

┌─────────────────────────────────────────┐
│ Data Filters                            │
├─────────────────────────────────────────┤
│ Mine Site: [Dropdown ▼]                 │
│ Assets: [Multi-select]                  │
│ Date Range: [Selector]                  │
│ Hide Zero Values: [Toggle]              │
│                                         │
│ ┌─ Value Filter ──────────────────[●]─┐ │
│ │ [=] [≠] [>] [≥] [<] [≤] [Range]     │ │
│ │ [  Enter value...  ]                 │ │
│ │ Filtering X data points              │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────┘

Interaction Details

  • Toggle on right controls enable/disable
  • When disabled, button group and inputs are grayed out
  • When "Range" selected, show two inputs: [Min] [Max]
  • When enabled and valid, show filtered count at bottom
  • Invalid input shows red border and error message

Data Structure

New Types

typescript
type ValueFilterMode = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'range';

Extended HeatmapControlsState

typescript
{
  // ... existing properties
  hideZeroValues: boolean;

  // New: Value filter
  valueFilterEnabled: boolean;
  valueFilterMode: ValueFilterMode;
  valueFilterValue: number | null;      // Single value modes
  valueFilterMin: number | null;        // Range mode min
  valueFilterMax: number | null;        // Range mode max
}

Default Values

typescript
valueFilterEnabled: false,
valueFilterMode: 'eq',
valueFilterValue: null,
valueFilterMin: null,
valueFilterMax: null,

Filter Logic

typescript
const filteredRows = useMemo(() => {
  let result = rows;

  // 1. Apply hideZeroValues filter first
  if (controls.hideZeroValues) {
    result = result.filter((row) => {
      const value = parseFloat(row.Location_AssetValue);
      return !isNaN(value) && value > 0;
    });
  }

  // 2. Apply value filter
  if (controls.valueFilterEnabled && isValidFilter()) {
    result = result.filter((row) => {
      const value = parseFloat(row.Location_AssetValue);
      if (isNaN(value)) return false;

      switch (controls.valueFilterMode) {
        case 'eq':   return value !== controls.valueFilterValue;
        case 'neq':  return value === controls.valueFilterValue;
        case 'gt':   return value <= controls.valueFilterValue;
        case 'gte':  return value < controls.valueFilterValue;
        case 'lt':   return value >= controls.valueFilterValue;
        case 'lte':  return value > controls.valueFilterValue;
        case 'range':
          return value < controls.valueFilterMin || value > controls.valueFilterMax;
        default: return false;
      }
    });
  }

  return result;
}, [rows, controls.hideZeroValues, controls.valueFilterEnabled,
    controls.valueFilterMode, controls.valueFilterValue,
    controls.valueFilterMin, controls.valueFilterMax]);

Validation Rules

ModeValidationError Message
Single value modesMust be valid number"Please enter a valid number"
Range modeBoth Min and Max required"Please enter valid numbers"
Range modeMin ≤ Max"Min must be less than or equal to Max"

Implementation Tasks

TaskDescriptionEst. Time
1Add ValueFilterMode type and extend HeatmapControlsState2 min
2Add default values to DEFAULT_CONTROLS2 min
3Update filteredRows useMemo with value filter logic5 min
4Add Value Filter UI component (toggle + buttons + inputs + validation)10 min
5Build verification and manual testing5 min

Total: ~25 minutes