Flow Meter PDF Export
Date: 2026-02-16 Scope: Add PDF export functionality to the Flow Meter feature using the existing shared export page infrastructure.
Problem
Flow Meter is the only major data feature without a proper export page. The current export is a simple PNG screenshot of charts via modern-screenshot. Other features (Dust Levels, Dust Ranger) have full-featured export pages with chart selection, AI-generated descriptions, branded PDF output, and progress tracking.
Solution
Follow the established export page pattern: create a dedicated /flow-meter/export route that reuses the shared useExportPage hook and UI components, with a new FlowMeterPdfExportService for PDF generation and a new Edge Function for AI chart descriptions.
Architecture
New Files:
src/features/flow-meter/config/chartConfig.ts # Chart options definition
src/features/flow-meter/services/flowMeterPdfExportService.ts # PDF generation (jsPDF + modern-screenshot)
src/app/(admin)/(pages)/flow-meter/export.tsx # Export page component
supabase/functions/generate-flow-meter-descriptions/ # AI description Edge Function
Modified Files:
src/routes/Routes.tsx # Add /flow-meter/export route
src/app/(admin)/(pages)/flow-meter/index.tsx # Replace PNG export with navigate to export pageChart Configuration
Five selectable charts:
| Key | Label | Default Selected |
|---|---|---|
dailySummary | Daily Water Usage Summary | ✅ |
waterUsageTimeline | Water Usage Timeline | ✅ |
calendarHeatmap | Usage Gap Calendar Heatmap | ✅ |
gapChart | Gap Analysis Chart | ❌ |
noDataDays | No Data Days Table | ❌ |
Data Flow
Flow Meter main page navigates to
/flow-meter/exportwithlocation.state:typescript{ siteSummary: selectedSiteSummary, // records, refills, dailySummaries, totalLitres, totalRefilled selectedSite: string, dateRange: { start: Date, end: Date }, chartType: "line" | "scatter", }Export page receives state, defines
chartOptions,buildAIRequestBody,handleExportPdfCalls
useExportPage()with Flow Meter-specific options:storageKey:flow-meter-{siteName}edgeFunctionName:"generate-flow-meter-descriptions"- Feature-specific
buildAIRequestBodyandonExport
Renders shared components:
ReportNameEditor,AIControlsPanel,ChartWithDescriptionwrappers,ExportSummarySection,ExportProgressModal
AI Description Edge Function
New Edge Function: generate-flow-meter-descriptions
System prompt positions the AI as a "Dustloc operational data analyst" that understands:
- Dustloc device water dispensing and refill patterns
- Daily usage trends and anomalies
- Operational efficiency (dispensing frequency, refill cycles)
- Data gaps and their operational implications
Request body:
{
model: string,
style: string,
flowMeterStats: {
totalLitres: number,
dailyAverage: number,
refillCount: number,
tankLevel: number,
totalRecords: number,
},
singleChart: string, // chart key
chartData: {
dailySummaries: DailySummary[],
records: FlowMeterRecord[],
refills: DustLocRefill[],
}
}Chart-specific prompts per singleChart key:
dailySummary— Analyze daily dispensing volume trends, identify peak/low usage dayswaterUsageTimeline— Analyze individual dispensing events over time, identify patterns in timing and volumecalendarHeatmap— Analyze the calendar view of usage gaps, identify periods of inactivitygapChart— Analyze gaps between dispensing events, identify operational disruptionsnoDataDays— Summarize days with no recorded data and potential causes
PDF Generation Service
FlowMeterPdfExportService follows DustLevelExportService pattern:
Cover Page:
- Dust Ranger logo + title "Dustloc Flow Meter Report"
- Site name, date range, timezone
- Summary stat cards (2×2 portrait, 1×4 landscape):
- Total Litres Dispensed
- Daily Average
- Refill Count
- Tank Level
- Total Records
- Active Days
Chart Pages:
- DOM discovery via
document.querySelectorAll("[data-export-chart]") - Chart capture with
domToJpeg(modern-screenshot) - Chart title + image + "KEY INSIGHTS" description box (orange left border)
- Supports portrait/landscape orientation
Summary Page:
- Optional summary/conclusion text (blue left border)
- Page numbers + copyright footer on all pages
Main Page Changes
Replace the current PNG export flow:
- Remove hidden
#all-charts-export-containerdiv - Remove
handleExportAllChartsfunction anduseChartExporthook usage - Change Export button to
navigate("/flow-meter/export", { state: {...} })
Route Definition
{
path: "/flow-meter/export",
name: "FlowMeterExport",
element: <FlowMeterExport />,
requiredModule: "flow_meter",
showDatePicker: true,
showSiteSelector: true,
}What Doesn't Change
- Existing
FlowMeterExportService(CSV/email) — untouched - Shared export infrastructure (
useExportPage,ChartWithDescription, etc.) — consumed as-is - Flow Meter chart components — reused on the export page
- Other features' export pages — unaffected