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

Usage Gap Analysis Feature Design

Overview

Add a new "Usage Gap Analysis" section to the Flow Meter page that visualizes which days have no Dustloc usage logs. This helps with operational monitoring - identifying equipment downtime or issues.

Requirements

  • Primary Use Case: Operational monitoring - identify when equipment might be down or there are issues
  • Scope: Selected site only (matches existing chart behavior)
  • Date Range: Uses the same DateRangeSelector as the main charts
  • Placement: New collapsible section below the existing "Recent Dispensing Events" table

Components

1. UsageCalendarHeatmap

A month-view calendar showing usage status for each day.

Visual Design:

  • Grid layout: 7 columns (Mon-Sun), rows for each week
  • Each day cell shows:
    • Day number
    • Color coding:
      • Green (bg-green-500) - Has usage data
      • Red/Orange (bg-red-400) - No usage data (gap)
      • Gray (bg-slate-200) - Outside date range or future dates
  • Hover tooltip shows: date, litres used (if any), number of events

Layout:

  • If date range spans multiple months, show each month as a separate mini-calendar side by side (horizontally scrollable if needed)
  • Month/year header above each calendar grid

2. UsageGapChart

A horizontal timeline highlighting consecutive no-data periods.

Visual Design:

  • Horizontal bar/timeline spanning the date range
  • Green segments - Days with usage data
  • Red/orange segments - Consecutive days without data (gaps)
  • X-axis shows dates (same format as existing charts)

Gap Blocks:

  • Each gap block shows the duration (e.g., "3 days") as a label
  • Hover tooltip shows: start date, end date, gap duration

Summary Stats (top-right corner):

  • Total days in range
  • Days with data
  • Days without data (gaps)
  • Longest gap duration

3. NoDataDaysTable

A simple table listing all days without usage data.

Columns:

DateDay of WeekGap DurationNotes
09 Jan 2026ThursdayStart of 3-day gap-
10 Jan 2026Friday--
11 Jan 2026SaturdayEnd of gapWeekend

Features:

  • Sorted by date (newest first by default)
  • "Day of Week" column helps identify if gaps correlate with weekends
  • "Gap Duration" indicates if day is start/middle/end of a consecutive gap
  • Pagination if many days (reuse existing pagination pattern)
  • Shows message "No gaps found - all days have usage data" if no gaps exist
  • Weekends (Sat/Sun) marked differently since no usage may be expected

File Structure

src/features/flow-meter/components/
├── UsageGapAnalysis/
│   ├── index.tsx                 # Main collapsible section wrapper
│   ├── UsageCalendarHeatmap.tsx  # Calendar heatmap component
│   ├── UsageGapChart.tsx         # Timeline gap indicator
│   └── NoDataDaysTable.tsx       # Summary table

Data Model

typescript
interface GapData {
  allDays: Date[];           // All days in the date range
  daysWithData: Set<string>; // YYYY-MM-DD format
  daysWithoutData: Date[];   // Days with no usage
  gaps: Gap[];               // Consecutive gap periods
}

interface Gap {
  startDate: Date;
  endDate: Date;
  duration: number;          // Number of days
}

interface DayStatus {
  date: Date;
  hasData: boolean;
  litresUsed?: number;
  eventCount?: number;
  isWeekend: boolean;
  gapInfo?: {
    position: 'start' | 'middle' | 'end' | 'single';
    gapDuration: number;
  };
}

Utility Function

typescript
function calculateGapData(
  dateRange: { start: Date; end: Date },
  dailySummaries: DailySummary[]
): GapData {
  // 1. Generate all days in the date range
  // 2. Create set of days that have data from dailySummaries
  // 3. Find days without data
  // 4. Group consecutive no-data days into gaps
  // Returns: { allDays, daysWithData, daysWithoutData, gaps }
}

Integration

In src/app/(admin)/(pages)/flow-meter/index.tsx:

tsx
import { UsageGapAnalysis } from "@/features/flow-meter/components/UsageGapAnalysis";

// ... inside the component, after the Records Table section:

{selectedSiteSummary && (
  <UsageGapAnalysis
    dateRange={dateRange}
    dailySummaries={selectedSiteSummary.dailySummaries}
    siteName={selectedSite}
  />
)}

UI Layout

┌─────────────────────────────────────────────────────────────┐
│ ▼ Usage Gap Analysis                              [Collapse]│
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────┐  ┌──────────────────────────────┐ │
│  │  Calendar Heatmap   │  │     Gap Indicator Chart      │ │
│  │  (Month view)       │  │     (Timeline view)          │ │
│  └─────────────────────┘  └──────────────────────────────┘ │
│                                                             │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              No-Data Days Summary Table              │  │
│  └──────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Dependencies

  • Recharts (already used) for the gap timeline chart
  • date-fns (already used) for date manipulation
  • No new dependencies needed

Acceptance Criteria

  1. New collapsible "Usage Gap Analysis" section appears below Records Table
  2. Calendar heatmap shows all days in range with color coding for data/no-data
  3. Gap indicator chart shows timeline with green (data) and red (gap) segments
  4. Summary table lists all no-data days with day of week and gap duration info
  5. All components respond to the same date range selector as existing charts
  6. All components filter by selected site
  7. Section is collapsible and remembers state in localStorage
  8. Hover tooltips provide detailed information
  9. "No gaps found" message when all days have data